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

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

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

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

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

C++

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

Q&A

解決済

1回答

5395閲覧

OpenCVでの顔、鼻検出の精度を高めたいです

KenKenPaPPa

総合スコア24

OpenCV

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

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

C++

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

0グッド

0クリップ

投稿2017/01/16 13:19

編集2017/01/16 13:35

お世話になってます。
現在大学3年生で最近プログラミングの勉強を始めた者です。
顔と鼻検出をしてそれを描画するプログラムを書いているところですが、
顔の中にない鼻は描画しないようにしています。
困っていることは、一人の顔に対して複数の鼻が検出された時です。
顔の中に鼻が2つ以上検出された時、顔中心にある方を描画するような
プログラムを書きたいのですが、具体的にどうかき足せば良いかわかりません。
教えていただきたいですm(_ _)m

開発環境
xcode opencv3 c++

C++

1int main(int argc, const char * argv[]) { 2 3 cv::Mat black_image = cv::Mat::zeros(cv::Size(640, 480), CV_8UC3); 4//分類器読み込み 5 std::string cascadeName = "/usr/local/Cellar/opencv3/3.2.0/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml"; 6 std::string cascadeName1 = "/usr/local/Cellar/opencv3/3.2.0/share/OpenCV/haarcascades/haarcascade_mcs_nose.xml"; 7 cv::CascadeClassifier cascade; 8 cv::CascadeClassifier cascade1; 9 if (!cascade.load(cascadeName)) return -1; 10 if (!cascade1.load(cascadeName1))return -1; 11 std::vector<cv::Rect> faces; 12 std::vector<cv::Rect> nose; 13 14 double ppl[10]; 15 int facex[10]; 16 int facey[10]; 17 int facer[10]; 18 19 cv::Mat frame; 20 cv::Mat input_image; 21 cv::Mat output_image; 22 frame = imread("/usr/local/kenshi/test1 (3).jpg",IMREAD_COLOR ); 23 //cv::resize(frame, frame, cv::Size(), 1000.0/frame.cols ,1000.0/frame.cols); 24 cvtColor(frame, input_image, CV_BGR2GRAY); 25 cv::equalizeHist(input_image, input_image); 26 output_image = frame; 27 28 flip(output_image, output_image, 1); 29 flip(input_image, input_image, 1); 30 31 cv::namedWindow("meter", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); 32 cv::namedWindow("window", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); 33 34 cascade.detectMultiScale(input_image, faces, 35 1.1, 3, 36 CV_HAAR_SCALE_IMAGE 37 , 38 cv::Size(600, 600)); 39 40 cascade1.detectMultiScale(input_image, nose, 41 1.1, 3, 42 CV_HAAR_SCALE_IMAGE 43 , 44 cv::Size(50, 50)); 45 46 std::vector<cv::Rect>::const_iterator r = faces.begin(); 47 std::vector<cv::Rect>::const_iterator r1 = nose.begin(); 48 49 int radius; 50 int radius1; 51 52 cv::Point center; 53 int b =0; 54 for (; r != faces.end(); ++r) { 55 56 center.x = cv::saturate_cast<int>((r->x + r->width*0.5)); 57 center.y = cv::saturate_cast<int>((r->y + r->height*0.5)); 58 radius = cv::saturate_cast<int>((r->width + r->height)*0.25); 59 cv::circle(output_image, center, radius, cv::Scalar(80, 80, 255), 3, 8, 0); 60 61 facex[b] = center.x; 62 facey[b] = center.y; 63 facer[b] = radius; 64 b++; 65 66 } 67 68 //色 69 int color[10]; 70 int t = 10000000; 71 for(int i = 0; i<10; i++) color[i] = 100 * i; 72 73 cv::Point center1; 74 int k = 0; 75 76 for (; r1 != nose.end(); ++r1) { 77 center1.x = cv::saturate_cast<int>((r1->x + r1->width*0.5)); 78 center1.y = cv::saturate_cast<int>((r1->y + r1->height*0.5)); 79 radius1 = cv::saturate_cast<int>((r1->width + r1->height)*0.25); 80 81 for(int i = 0; i < b; i++){ 82 int u = (facex[i]-center1.x)*(facex[i]-center1.x)+(facey[i]-center1.y)*(facey[i]-center1.y); 83 int m = facer[i] * facer[i]; 84 85 if(u < m){ 86 87 88 cv::circle(output_image, center1, radius1, cv::Scalar(color[i], 0, color[i]), 3, 8, 0); 89 //顔、鼻、角度セットで出力して角度を配列に格納 90 91 printf("nose(%d,%d)\n", center1.x, center1.y); 92 printf("face(%d,%d)\n", facex[i], facey[i]); 93 printf("radius%d\n", facer[i]); 94 double rad = angle(int(facex[i]), int(center1.x)); 95 96 ppl[k] = rad; 97 printf("k=%d,angle:%f\n", k,rad ); 98 printf("u=%d,m=%d\n",u,m); 99 100 k++; 101 break; 102 103 } 104 } 105 } 106 107 cv::Point circle; 108 cv::Point circle1; 109 for(int i = 0; i < b; i++){ 110 circle.x = 60 + 120 * (i); 111 circle.y = 60 ; 112 cv::circle(black_image, circle, 50, cv::Scalar(80, 80, 255), -1, 4, 0); 113 114 circle1.x = circle.x - 50 * cos(M_PI / 2 - ppl[i]); 115 circle1.y = circle.y - 50 * sin(M_PI / 2 - ppl[i]); 116 117 cv::line(black_image, circle, circle1, cv::Scalar(color[i], 0, color[i]), 3, 1, 0); 118 119 } 120 121 cv::resize(output_image, output_image, cv::Size(), 1000.0/output_image.cols ,1000.0/output_image.cols); 122 123 imshow("meter", black_image); 124 imshow("window", output_image); 125 126 cv::waitKey(0); 127 return 0; 128}

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

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

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

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

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

guest

回答1

0

ベストアンサー

顔、鼻を最初ペアにする作業をして、描画は別のタイミングにしましょう。

C++

1struct DetectedArea 2{ 3 cv::Point center; 4 int radius; 5 6 bool Contains(DetectedArea area) 7 { 8 // CenterがArea内だったらtrue, そうじゃなければfalse とか 9 } 10} 11 12struct Person 13{ 14 DetectedArea face; 15 DetectedArea nose; 16 bool has_nose; 17 Person() 18 { 19 has_nose = false; 20 } 21} 22 23// cv::RectをDetectedAreaに変換する関数を作る 24DetectedArea RectToArea(const cv::Rect &rect) 25{ 26 DetectedArea area; 27 area.center.x = cv::saturate_cast<int>((rect.x + rect.width*0.5));; 28 area.center.y = cv::saturate_cast<int>((rect.y + rect.height*0.5)); 29 area.radius = cv::saturate_cast<int>((rect.width + rect.height)*0.25);; 30} 31 32 33// main関数内 34std::vector<Face> people; 35 36// ペアリング 37for (std::vector<cv::Rect>::const_iterator face = faces.begin(); 38 face != faces.end(); ++face) { 39 40 Person person; 41 42 // まず顔 43 person.face = RectToArea(*face); 44 45 // 次に鼻を検出する 46 // 2個以上あったらどっちにするかを決める 47 for (std::vector<cv::Rect>::const_iterator nose = noses.begin(); 48 nose != noses.end(); ++nose) { 49 DetectedArea area = RectToArea(*nose); 50 if (person.face.Contains(area)) 51 { 52 // 顔の範囲内の鼻が見つかった 53 if (!person.has_nose || 54 /* person.nose より新しい 鼻 がふさわしい時はという条件 */) 55 { 56 person.has_nose = true; 57 person.nose = area; 58 } 59 } 60 } 61 62 people.push_back(person); 63} 64 65// 描画 66for (std::vector<Person>::const_iterator person = people.begin(); 67 person != people.end(); ++person) 68{ 69 // person.Face ... 書いて 70 if (person.has_nose) 71 { 72 // person.nose ... 書く! 73 } 74}

投稿2017/01/17 03:17

haru666

総合スコア1591

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

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

KenKenPaPPa

2017/01/18 02:23

とてもわかりやすいプログラムで助かりました! ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問