###前提・実現したいこと
OpenCVで元からあるサンプルコード「smiledetect.cpp」を用いて笑顔検出のシステムを作っています。
検出機能を実装中に以下の問題が発生しました。
###発生している問題・状況
問題:笑顔検出されていたら四角で囲むはずが、囲まれていない。 状況:リアルタイムで検出している顔だけが移っている状態。 画像に笑顔検出のプログラムを実行したところ、画像のようになった。 [画像での笑顔検出](https://imgur.com/a/npC1H)
###該当のソースコード
C++
1#include "opencv2/objdetect.hpp" 2#include "opencv2/highgui.hpp" 3#include "opencv2/imgproc.hpp" 4#include "opencv2/opencv.hpp" 5#include <iostream> 6using namespace std; 7using namespace cv; 8static void help() 9{ 10cout<<"Program build!!!! "<<CV_VERSION<< "\n"<<endl; 11} 12void detectAndDraw( Mat& img, CascadeClassifier& cascade, 13 CascadeClassifier& nestedCascade, 14 double scale, bool tryflip ); 15string cascadeName; 16string nestedCascadeName; 17int main(int argc, const char** argv) 18{ 19 VideoCapture capture; 20 Mat frame, image; 21 string inputName; 22 bool tryflip; 23 help(); 24 CascadeClassifier cascade, nestedCascade; 25 double scale; 26 //カメラからのビデオキャプチャを初期化する 27 CvCapture*videoCapture = cvCreateCameraCapture(1); 28 if(videoCapture ==NULL) 29 { 30 return -1; 31 } 32 cv::CommandLineParser parser(argc, argv, 33 "{help h||}{scale|1|}" 34 "{cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|}" 35 "{smile-cascade|../../data/haarcascades/haarcascade_smile.xml|}" 36 "{try-flip||}{@input||}"); 37 if (parser.has("help")) 38 { 39 help(); 40 return 0; 41 } 42 //ウィンドウを作成する 43 char windowName[]="camera"; 44 cvNamedWindow(windowName,CV_WINDOW_AUTOSIZE); 45 while(cvWaitKey(1)==-1) 46 { 47 //カメラから1フレーム習得する 48 IplImage*image=cvQueryFrame(videoCapture); 49 //ウィンドウに画像を表示する 50 cvShowImage(windowName,image); 51 } 52 cascadeName = parser.get<string>("cascade"); 53 nestedCascadeName = parser.get<string>("smile-cascade"); 54 tryflip = parser.has("try-flip"); 55 inputName = parser.get<string>("@input"); 56 scale = parser.get<int>("scale"); 57 if (!parser.check()) 58 { 59 help(); 60 return 1; 61 } 62 if (scale < 1) 63 scale = 1; 64 if( !cascade.load( cascadeName ) ) 65 { 66 cerr << "ERROR: Could not load face cascade" << endl; 67 help(); 68 return -1; 69 } 70 if( !nestedCascade.load( nestedCascadeName ) ) 71 { 72 cerr << "ERROR: Could not load smile cascade" << endl; 73 help(); 74 return -1; 75 } 76 if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) ) 77 { 78 int c = inputName.empty() ? 0 : inputName[0] - '0' ; 79 if(!capture.open(c)) 80 cout << "Capture from camera #" << c << " didn't work" << endl; 81 } 82 else if( inputName.size() ) 83 { 84 if(!capture.open( inputName )) 85 cout << "Could not read " << inputName << endl; 86 } 87 if( capture.isOpened() ) 88 { 89 cout << "Video capturing has been started ..." << endl; 90 cout << endl << "NOTE: Smile intensity will only be valid after a first smile has been detected" << endl; 91 while(1) 92 { 93 capture >> frame; 94 if( frame.empty() ) 95 break; 96 Mat frame1 = frame.clone(); 97 detectAndDraw( frame1, cascade, nestedCascade, scale, tryflip ); 98 char c = (char)waitKey(10); 99 if( c == 27 || c == 'q' || c == 'Q' ){ 100 break; } 101 //else if(c==32|| c=='s'||c=='S'){ 102 //cv::imwrite("smile.png", frame); } 103 } 104 } 105 else 106 { 107 cerr << "ERROR: Could not initiate capture" << endl; 108 help(); 109 return -1; 110 } 111 //ビデオキャプチャを開放する 112 cvReleaseCapture(&videoCapture); 113 //ウィンドウを破棄する 114 cvDestroyWindow(windowName); 115 return 0; 116 } 117 void detectAndDraw( Mat& img, CascadeClassifier& cascade, 118 CascadeClassifier& nestedCascade, 119 double scale, bool tryflip) 120 { 121 vector<Rect> faces, faces2; 122 const static Scalar colors[] = 123 { 124 Scalar(255,0,0), 125 Scalar(255,128,0), 126 Scalar(255,255,0), 127 Scalar(0,255,0), 128 Scalar(0,128,255), 129 Scalar(0,255,255), 130 Scalar(0,0,255), 131 Scalar(255,0,255) 132 }; 133 Mat gray, smallImg; 134 cvtColor( img, gray, COLOR_BGR2GRAY ); 135 double fx = 1 / scale; 136 resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR ); 137 equalizeHist( smallImg, smallImg ); 138 cascade.detectMultiScale( smallImg, faces, 139 1.1, 2, 0 140 //|CASCADE_FIND_BIGGEST_OBJECT 141 //|CASCADE_DO_ROUGH_SEARCH 142 |CASCADE_SCALE_IMAGE, 143 Size(30, 30) ); 144 if( tryflip ) 145 { 146 flip(smallImg, smallImg, 1); 147 cascade.detectMultiScale( smallImg, faces2, 148 1.5, 2, 0 149 //|CASCADE_FIND_BIGGEST_OBJECT 150 //|CASCADE_DO_ROUGH_SEARCH 151 |CASCADE_SCALE_IMAGE, 152 Size(30, 30) ); 153 for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r ) 154 { 155 faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height)); 156 } 157 } 158 for ( size_t i = 0; i < faces.size(); i++ ) 159 { 160 Rect r = faces[i]; 161 Mat smallImgROI; 162 vector<Rect> nestedObjects; 163 Point center; 164 Scalar color = colors[i%8]; 165 int radius; 166int face[] = {cv::FONT_HERSHEY_SIMPLEX, cv::FONT_HERSHEY_PLAIN, cv::FONT_HERSHEY_DUPLEX, cv::FONT_HERSHEY_COMPLEX, 167 cv::FONT_HERSHEY_TRIPLEX, cv::FONT_HERSHEY_COMPLEX_SMALL, cv::FONT_HERSHEY_SCRIPT_SIMPLEX, 168 cv::FONT_HERSHEY_SCRIPT_COMPLEX, cv::FONT_ITALIC}; 169 double aspect_ratio = (double)r.width/r.height; 170 if( 0.75 < aspect_ratio && aspect_ratio < 1.3 ) 171 { 172 center.x = cvRound((r.x + r.width*0.5)*scale); 173 center.y = cvRound((r.y + r.height*0.5)*scale); 174 radius = cvRound((r.width + r.height)*0.25*scale); 175 circle( img, center, radius, color, 3, 8, 0 ); 176 } 177 else 178 rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)), 179 cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),color, 3, 8, 0); 180 const int half_height=cvRound((float)r.height/2); 181 r.y=r.y + half_height; 182 r.height = half_height-1; 183 smallImgROI = smallImg( r ); 184 nestedCascade.detectMultiScale( smallImgROI, nestedObjects, 185 1.1, 0, 0 186 //|CASCADE_FIND_BIGGEST_OBJECT 187 //|CASCADE_DO_ROUGH_SEARCH 188 //|CASCADE_DO_CANNY_PRUNING 189 |CASCADE_SCALE_IMAGE, 190 Size(30, 30) ); 191 // The number of detected neighbors depends on image size (and also illumination, etc.). The 192 // following steps use a floating minimum and maximum of neighbors. Intensity thus estimated will be 193 //accurate only after a first smile has been displayed by the user. 194 const int smile_neighbors = (int)nestedObjects.size(); 195 static int max_neighbors=-1; 196 static int min_neighbors=-1; 197 if (min_neighbors == -1) 198 min_neighbors = smile_neighbors; 199 max_neighbors = MAX(max_neighbors, smile_neighbors); 200 // Draw rectangle on the left side of the image reflecting smile intensity 201 float intensityZeroOne = ((float)smile_neighbors - min_neighbors) / (max_neighbors - min_neighbors + 1); 202 //(float)img.rows 203 double rect_height = cvRound((float)img.rows* intensityZeroOne)/2; 204 char rectchar[256]; 205 Scalar col = Scalar((float)255 * intensityZeroOne, 0, 0); 206 sprintf(rectchar, "%f", rect_height); 207 //greenline 208 line(img,Point(0,240), Point(100,240), Scalar(0,200,0), 5, CV_AA); 209 if(rect_height>0) 210 //positive line 211 rectangle(img, cvPoint(0, 235), cvPoint(img.cols/10, 240-rect_height), CV_RGB(200,0,0), CV_FILLED); 212 else 213 //negative line 214 rectangle(img, cvPoint(0,245), cvPoint(img.cols/10,480+rect_height*50), CV_RGB(0,0,200), CV_FILLED); 215 //Text 216 rectangle(img, cvPoint(400,430),cvPoint(630,395),CV_RGB(0,0,200), 3, 4); 217 putText(img, rectchar, cv::Point(400,425), face[0], 1.2, cv::Scalar(0,0,200), 2, CV_AA); 218 } 219 imshow( "result", img ); 220}
###試したこと
コマンド「lsusb」を打って、webカメラが認識されていることは分かっています。
###補足情報(言語/FW/ツール等のバージョンなど)
Webカメラを使っての、リアルタイム表示は出来ています。
言語:c++
環境:Windows8
仮想空間:VMware Player
ツール:OpenCV3.3.1
参考サイト:https://so-zou.jp/software/tech/library/opencv/camera/ https://github.com/opencv/opencv/blob/master/samples/cpp/smiledetect.cpp
回答2件
あなたの回答
tips
プレビュー