質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

934閲覧

リアルタイムエッジ検出

kotetu

総合スコア34

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/02/10 11:55

編集2018/02/10 12:15

閲覧有難うございます。

前回の質問から、少しずつですが開発をしています。

リアルタイム笑顔検出は、できるようになりました。
現在行おうとしていることが、リアルタイムで得た動画にエッジ検出を適応することです。
新しく加えた箇所は、以下のとおりです。

//////////////////////////////////////////////////// capture >> frame; // (2)calculate the first image derivatives using an Sobel operator Mat tmp_img, sobel_img, laplacian_img, canny_img; Sobel(frame, tmp_img, CV_32F, 1, 1); convertScaleAbs(tmp_img, sobel_img, 1, 0); // (3)calculate the Laplacian of an image Laplacian(frame, tmp_img, CV_32F, 3); convertScaleAbs(tmp_img, laplacian_img, 1, 0); // (4)implement the Canny algorithm for edge detection Canny(frame, canny_img, 50, 200); // (5)show original gray and their edge images respectively, // and quit when any key pressed imshow("Canny", canny_img); waitKey(0); //////////////////////////////////////////

下記が全体のコード文です。コード文の下に、実行した際のエラーを載せておきます。
よろしくお願いします。

C++

1#include "opencv2/objdetect.hpp" 2#include "opencv2/highgui.hpp" 3#include "opencv2/imgproc.hpp" 4#include "opencv2/opencv.hpp" 5#include "opencv2/highgui/highgui.hpp" 6#include <iostream> 7using namespace std; 8using namespace cv; 9static void help() 10{ 11cout<<"Program build!!!! "<<CV_VERSION<< "\n"<<endl; 12} 13void detectAndDraw( Mat& img, CascadeClassifier& cascade, 14 CascadeClassifier& nestedCascade, 15 double scale, bool tryflip ); 16string cascadeName; 17string nestedCascadeName; 18int main(int argc, const char** argv) 19{ 20 VideoCapture capture; 21 22 Mat frame, image; 23 string inputName; 24 bool tryflip; 25 help(); 26 CascadeClassifier cascade, nestedCascade; 27 double scale; 28 29 //////////////////////////////////////////////////// 30 上記のコードの場所 31 ////////////////////////////////////////// 32 33 cv::CommandLineParser parser(argc, argv, 34 "{help h||}{scale|1|}" 35 "{cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|}" 36 "{smile-cascade|../../data/haarcascades/haarcascade_smile.xml|}" 37 "{try-flip||}{@input||}"); 38 if (parser.has("help")) 39 { 40 help(); 41 return 0; 42 } 43 44 cascadeName = parser.get<string>("cascade"); 45 nestedCascadeName = parser.get<string>("smile-cascade"); 46 tryflip = parser.has("try-flip"); 47 inputName = parser.get<string>("@input"); 48 scale = parser.get<int>("scale"); 49 if (!parser.check()) 50 { 51 help(); 52 return 1; 53 } 54 if (scale < 1) 55 scale = 1; 56 if( !cascade.load( cascadeName ) ) 57 { 58 cerr << "ERROR: Could not load face cascade" << endl; 59 help(); 60 return -1; 61 } 62 if( !nestedCascade.load( nestedCascadeName ) ) 63 { 64 cerr << "ERROR: Could not load smile cascade" << endl; 65 help(); 66 return -1; 67 } 68 if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) ) 69 { 70 int c = inputName.empty() ? 0 : inputName[0] - '0' ; 71 if(!capture.open(c)) 72 cout << "Capture from camera #" << c << " didn't work" << endl; 73 } 74 else if( inputName.size() ) 75 { 76 if(!capture.open( inputName )) 77 cout << "Could not read " << inputName << endl; 78 } 79 if( capture.isOpened() ) 80 { 81 cout << "Video capturing has been started ..." << endl; 82 cout << endl << "NOTE: Smile intensity will only be valid after a first smile has been detected" << endl; 83 while(1) 84 { 85 capture >> frame; 86 if( frame.empty() ) 87 break; 88 Mat frame1 = frame.clone(); 89 detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip ); 90 char c = (char)waitKey(10); 91 if( c == 27 || c == 'q' || c == 'Q' ) 92 { 93 break; 94 } 95 } 96 } 97 else 98 { 99 cerr << "ERROR: Could not initiate capture" << endl; 100 help(); 101 return -1; 102 } 103 return 0; 104} 105void detectAndDraw( Mat& img, CascadeClassifier& cascade, 106 CascadeClassifier& nestedCascade, 107 double scale, bool tryflip) 108{ 109 vector<Rect> faces, faces2; 110 const static Scalar colors[] = 111 { 112 Scalar(255,0,0), 113 Scalar(255,128,0), 114 Scalar(255,255,0), 115 Scalar(0,255,0), 116 Scalar(0,128,255), 117 Scalar(0,255,255), 118 Scalar(0,0,255), 119 Scalar(255,0,255) 120 }; 121 Mat gray, smallImg; 122 cvtColor( img, gray, COLOR_BGR2GRAY ); 123 double fx = 1 / scale; 124 resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); 125 equalizeHist( smallImg, smallImg ); 126 cascade.detectMultiScale( smallImg, faces, 127 1.1, 2, 0 128 //|CASCADE_FIND_BIGGEST_OBJECT 129 //|CASCADE_DO_ROUGH_SEARCH 130 |CASCADE_SCALE_IMAGE, 131 Size(30, 30) ); 132 if( tryflip ) 133 { 134 flip(smallImg, smallImg, 1); 135 cascade.detectMultiScale( smallImg, faces2, 136 1.5, 2, 0 137 //|CASCADE_FIND_BIGGEST_OBJECT 138 //|CASCADE_DO_ROUGH_SEARCH 139 |CASCADE_SCALE_IMAGE, 140 Size(30, 30) ); 141 for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r ) 142 { 143 faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height)); 144 } 145 } 146 for ( size_t i = 0; i < faces.size(); i++ ) 147 { 148 Rect r = faces[i]; 149 Mat smallImgROI; 150 vector<Rect> nestedObjects; 151 Point center; 152 Scalar color = colors[i%8]; 153 int radius; 154 int face[] = {cv::FONT_HERSHEY_SIMPLEX, cv::FONT_HERSHEY_PLAIN, cv::FONT_HERSHEY_DUPLEX, cv::FONT_HERSHEY_COMPLEX, 155 cv::FONT_HERSHEY_TRIPLEX, cv::FONT_HERSHEY_COMPLEX_SMALL, cv::FONT_HERSHEY_SCRIPT_SIMPLEX, 156 cv::FONT_HERSHEY_SCRIPT_COMPLEX, cv::FONT_ITALIC}; 157 double aspect_ratio = (double)r.width/r.height; 158 if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) 159 { 160 center.x = cvRound((r.x + r.width*0.5)*scale); 161 center.y = cvRound((r.y + r.height*0.5)*scale); 162 radius = cvRound((r.width + r.height)*0.25*scale); 163 circle( img, center, radius, color, 3, 8, 0 ); 164 165 } 166 else 167 rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)), 168 cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),color, 3, 8, 0); 169 const int half_height=cvRound((float)r.height/2); 170 r.y=r.y + half_height; 171 r.height = half_height-1; 172 smallImgROI = smallImg( r ); 173 nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 174 1.1, 0, 0 175 //|CASCADE_FIND_BIGGEST_OBJECT 176 //|CASCADE_DO_ROUGH_SEARCH 177 //|CASCADE_DO_CANNY_PRUNING 178 |CASCADE_SCALE_IMAGE, 179 Size(30, 30) ); 180 // The number of detected neighbors depends on image size (and also illumination, etc.). The 181 // following steps use a floating minimum and maximum of neighbors. Intensity thus estimated will be 182 //accurate only after a first smile has been displayed by the user. 183 const int smile_neighbors = (int)nestedObjects.size(); 184 static int max_neighbors=-1; 185 static int min_neighbors=-1; 186 if (min_neighbors == -1) 187 min_neighbors = smile_neighbors; 188 max_neighbors = MAX(max_neighbors, smile_neighbors); 189 // Draw rectangle on the left side of the image reflecting smile intensity 190 float intensityZeroOne = ((float)smile_neighbors - min_neighbors) / (max_neighbors - min_neighbors + 1); 191 //(現在の笑顔-笑顔の最小値)/(笑顔の最大値 - 笑顔の最小値 + 1) 192 double rect_height = cvRound((float)img.rows* intensityZeroOne)/2; 193 char rectchar[256]; 194 char maxsmile[256]; 195 char minsmile[256]; 196 Scalar col = Scalar((float)255 * intensityZeroOne, 0, 0); 197 sprintf(rectchar, "%f", rect_height);//対応しているのはdouble型 198 sprintf(maxsmile, "%d", max_neighbors);//対応しているのはint型 199 sprintf(minsmile, "%d", min_neighbors);//対応しているのはint型 200 201 //greenline 202 line(img,Point(0,240), Point(70,240), Scalar(0,200,0), 5, CV_AA); 203 204 //上から笑顔度、笑顔度の最大値、笑顔度の最小値、現在の笑顔度 205 putText(img, "smile", cvPoint(488,30), face[2], 0.5, cvScalar(0,0,200), 1, CV_AA); 206 putText(img, "degree", cvPoint(478,50), face[2], 0.5, cvScalar(0,0,200), 1, CV_AA); 207 putText(img, "MAX", cvPoint(488,75), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA); 208 putText(img, maxsmile, cvPoint(540,75), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA); 209 putText(img, "MIN", cvPoint(488,95), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA); 210 putText(img, minsmile, cvPoint(540,95), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA); 211 //putText(img, imgrow, cvPoint(540,115), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA); 212 213 if(rect_height>0) 214 { 215 rectangle(img, cvPoint(0, 235), cvPoint(img.cols/10, 240-rect_height), CV_RGB(200,0,0), CV_FILLED); 216 putText(img, "GOOD", cvPoint(535,50), face[0], 1.2, cv::Scalar(0,0,200), 2, CV_AA); 217 } 218 else 219 { 220 rectangle(img, cvPoint(0,245), cvPoint(img.cols/10,240-rect_height), CV_RGB(0,0,200), CV_FILLED); 221 putText(img, "BAD", cvPoint(535,50), face[0], 1.2, cv::Scalar(0,0,200), 2, CV_AA); 222 } 223 } 224 imshow( "result", img ); 225} 226

コンパイルは、通ります。
しかし、実行した際に以下のようなエラーを吐いてしまいます。

  • OpenCV Error: Assertion failed (dims <= 2 && step[0] > 0) in locateROI, file /home/ユーザー名/Install-OpenCV/Ubuntu/OpenCV/opencv-3.3.1/modules/core/src/matrix.cpp, line 991
  • terminate called after throwing an instance of 'cv::Exception'
  • what(): /home/ユーザー名/Install-OpenCV/Ubuntu/OpenCV/opencv-3.3.1/modules/core/src/matrix.cpp:991: error: (-215) dims <= 2 && step[0] > 0 in function locateROI

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2018/02/10 11:58

あのさー...こんなに長いコードなら、せめてそのエラーがどの行で出たかくらいは突き止めてから質問してよー
guest

回答2

0

自己解決

フレーム開放をしないといけない処理なのに、フレーム開放せずに実行していた。

加えた箇所としては、以下のとおりである。
if( capture.isOpened() )
{
cout << "Video capturing has been started ..." << endl;
cout << endl << "NOTE: Smile intensity will only be valid after a first smile has been detected" << endl;
while(1)
{
capture >> frame;
if( frame.empty() )
break;
Mat frame1 = frame.clone();
detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip );
// (2)calculate the first image derivatives using an Sobel operator
Mat tmp_img, sobel_img, laplacian_img, canny_img;
Sobel(frame1, tmp_img, CV_32F, 1, 1);
convertScaleAbs(tmp_img, sobel_img, 1, 0);
// (3)calculate the Laplacian of an image
Laplacian(frame1, tmp_img, CV_32F, 3);
convertScaleAbs(tmp_img, laplacian_img, 1, 0);
// (4)implement the Canny algorithm for edge detection
Canny(frame1, canny_img, 50, 200);
// (5)show original gray and their edge images respectively,
// and quit when any key pressed
imshow("Canny", canny_img);

char c = (char)waitKey(10);
if( c == 27 || c == 'q' || c == 'Q' )
{
break;
}
}
}

今回から、学んだことはカメラを使うなどUSB接続機器を使って何か処理したい場合は、フレーム開放、カメラなどの機器を開放?しているisOpened()の所に処理を書くことですね。

投稿2018/02/12 06:10

kotetu

総合スコア34

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

新しく加えた箇所 を挿入する前はちゃんと動いてたってこと?
そのエラーを吐くのは 新しく加えた箇所 のどこか、ってこと?

投稿2018/02/10 15:04

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kotetu

2018/02/11 08:20

はい、そのです。
episteme

2018/02/11 08:43

だったら デバッガでステップ実行すりゃわかるんじゃなくて?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問