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

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

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

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

解決済

Open CVを使った肌色変換の誤作動

sterengers
sterengers

総合スコア4

OpenCV

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

1回答

-1評価

0クリップ

324閲覧

投稿2021/12/02 04:40

前提・実現したいこと

opencvを使って指定範囲内の顔だけ色を変換するというのを組んでみました
しかし認識はしているのでしょうが全ての範囲が灰色に変わってしまいます。
■■な機能を実装中に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

エラーではなく機能していない

該当のソースコード

#include <iostream> //入出力関連ヘッダ #include <GLUT/glut.h> //OpenGL関連ヘッダ #include <opencv2/opencv.hpp> //OpenCV関連ヘッダ //関数名の宣言 void initGL(void); // OpenGLの初期化 void initCV(void); // OpenCVの初期化 void display(void); // 描画関数 void idle(void); void reshape(int w, int h); void mouse(int button, int state, int x, int y); void motion(int x, int y); void keyboard(unsigned char key, int x, int y); //グローバル変数 cv::VideoCapture capture; // 映像キャプチャ用変数 cv::Mat originalImage; cv::Mat frameImage; cv::Mat hsvImage; cv::Mat tempImage; cv::Size imageSize; cv::CascadeClassifier faceClassifier; // 顔認識用分類器 int mX, mY, mState, mButton; //マウス座標 int winW, winH; // ウィンドウサイズ char *cameraTexture; // カメラ画像用配列 // 顔色の変更 void change_face_color(cv::Mat& faceImage, cv::Mat& hsvImage, cv::Rect rect) { // 色解析しやすいようにHSV色空間に変換 cv::cvtColor(faceImage, hsvImage, cv::COLOR_BGR2GRAY); for(int j=rect.y; j<rect.y+rect.height; j++) { for(int i=rect.x; i<rect.x+rect.width; i++) { cv::Vec3b s = hsvImage.at<cv::Vec3b>(j, i); // 肌色領域のみ変換 if(s[0]> 0 && s[0]< 50 && s[1]>45 && s[1]<255 && s[2]>45 && s[2]<255) { s[0] = 0; hsvImage.at<cv::Vec3b>(j, i) = s; } } } cv::cvtColor(hsvImage, faceImage, cv::COLOR_RGBA2RGB); } //main関数 int main(int argc, char* argv[]) { //OpenGL初期化 glutInit(&argc, argv); //OpenCV初期設定処理 initCV(); //OpenGL初期設定処理 initGL(); //イベント待ち無限ループ glutMainLoop(); return 0; } //OpenGL初期設定処理 void initGL(void) { //初期設定 glutInitWindowSize(640, 480); //ウィンドウサイズ指定 glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); //ディスプレイモード設定 //OpenGLウィンドウ生成 glutCreateWindow("DIP12"); //ウィンドウ消去色設定 glClearColor(0.0, 0.0, 0.2, 1.0); //機能有効化 glEnable(GL_LIGHTING); //陰影付けの有効化 glEnable(GL_LIGHT0); //光源0の有効化 glEnable(GL_DEPTH_TEST); //デプスバッファの有効化 //コールバック関数 glutDisplayFunc(display); //ディスプレイコールバック関数の指定 glutIdleFunc(idle); //アイドルコールバック関数の指定 glutReshapeFunc(reshape); //リサイズコールバック関数の指定 glutMouseFunc(mouse); //マウスクリックコールバック関数の指定("mouse()") glutMotionFunc(motion); //マウスドラッグコールバック関数の指定("motion()") glutKeyboardFunc(keyboard); //キーボードコールバック関数の指定("keyboard()") // カメラ映像描画用配列 cameraTexture = new char [640*480*3]; //3バイトカラー画像 } //OpenCV初期設定処理 void initCV() { //カメラキャプチャの初期化 imageSize = cv::Size(640,480); capture = cv::VideoCapture(0); if (capture.isOpened()==0) { //カメラが見つからないときはメッセージを表示して終了 printf("Camera not found\n"); exit(1); } capture >> originalImage; cv::resize(originalImage, frameImage, imageSize); //OpenCVウィンドウ生成 cv::namedWindow("Frame"); //3チャンネル画像"hsvImage"と"tempImage"の確保(ビデオと同サイズ) hsvImage = cv::Mat(imageSize, CV_8UC3); tempImage = cv::Mat(imageSize, CV_8UC3); // ①正面顔検出器の読み込み faceClassifier.load("haarcascades/haarcascade_frontalface_default.xml"); } //ディスプレイコールバック関数 void display(void) { //------------------------------CV------------------------------ //ビデオキャプチャから1フレーム画像取得 capture >> originalImage; cv::resize(originalImage, frameImage, imageSize); //フレーム画像表示 cv::imshow("Frame", frameImage); // ②検出情報を受け取るための配列を用意する std::vector<cv::Rect> faces; // ③画像中から検出対象の情報を取得する faceClassifier.detectMultiScale(frameImage, faces, 1.1, 3, 0, cv::Size(20,20)); // ④顔領域の検出 for (int i = 0; i < faces.size(); i++) { // 検出情報から顔の位置情報を取得 cv::Rect face = faces[i]; // 大きさによるチェック。 if(face.width*face.height < 100*100){ continue; // 小さい矩形は採用しない } face.width = face.width*1.2; face.height = face.height*1.85; face.x = face.x - face.width*0.1; face.y = face.y - face.height*0.3; // ⑤画像の加工 change_face_color(frameImage, hsvImage, face); // 取得した顔の位置情報に基づき、矩形描画を行う // cv::rectangle(frameImage, // cv::Point(face.x, face.y), // cv::Point(face.x + face.width, face.y + face.height), // CV_RGB(255, 0, 0), // 3, CV_AA); } // ⑥カメラ画像を配列cameraTextureに複写(OpenCVとOpenGLでは色の並びが異なることに注意:OpenCV->BGR, OpenGL->RGB) for(int j=0; j<imageSize.height; j++){ for(int i=0; i<imageSize.width; i++){ cv::Vec3b s = frameImage.at<cv::Vec3b>(j, i); cameraTexture[(j*imageSize.width + i)*3 + 0] = s[2]; cameraTexture[(j*imageSize.width + i)*3 + 1] = s[1]; cameraTexture[(j*imageSize.width + i)*3 + 2] = s[0]; } } //------------------------------CG------------------------------ //ウィンドウ内消去 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //行列初期化 glLoadIdentity(); // ⑦カメラ画像をテクスチャマッピング glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, imageSize.width, imageSize.height, GL_RGB, GL_UNSIGNED_BYTE, cameraTexture); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(-imageSize.width/2, imageSize.height/2); glTexCoord2f(0, 1); glVertex2f(-imageSize.width/2, -imageSize.height/2); glTexCoord2f(1, 1); glVertex2f( imageSize.width/2, -imageSize.height/2); glTexCoord2f(1, 0); glVertex2f( imageSize.width/2, imageSize.height/2); glEnd(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); //描画実行 glutSwapBuffers(); } //アイドルコールバック関数 void idle(void) { glutPostRedisplay(); //ディスプレイイベント発生 } //リサイズコールバック関数 void reshape(int w, int h) { glViewport(0, 0, w, h); //ウィンドウ全体が描画対象 glMatrixMode(GL_PROJECTION); //投影変換行列を計算対象に設定 glLoadIdentity(); //行列初期化 gluOrtho2D(-w/2, w/2, -h/2, h/2); //直投影 glMatrixMode(GL_MODELVIEW); //モデルビュー変換行列を計算対象に設定 winW = w; winH = h; } //マウスクリックコールバック関数 void mouse(int button, int state, int x, int y) { //マウスボタンが押された if (state==GLUT_DOWN) { mX = x; mY = y; mState = state; mButton = button; //マウス情報保持 } } //マウスドラッグコールバック関数 void motion(int x, int y) { //マウスの移動量を角度変化量に変換 if(mButton == GLUT_LEFT_BUTTON){ } else if(mButton == GLUT_RIGHT_BUTTON){ } mX = x; mY = y; } //キーボードコールバック関数(key:キーの種類,x,y:座標) void keyboard(unsigned char key, int x, int y) { switch (key) { case 'q': case 'Q': case '\033': // '\033'はESCのASCIIコード exit(0); default: break; } }

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

OpenCV

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。