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

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

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

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

コードレビュー

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

Q&A

解決済

1回答

965閲覧

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

sterengers

総合スコア5

OpenCV

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

コードレビュー

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

0グッド

0クリップ

投稿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; } }

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

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

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

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

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

guest

回答1

0

ベストアンサー

関数 change_face_color 内:

// 色解析しやすいようにHSV色空間に変換
cv::cvtColor(faceImage, hsvImage, cv::COLOR_BGR2GRAY);

コメントとは異なり,HSVに変換してませんよねコレ.
末尾にある変換

cv::cvtColor(hsvImage, faceImage, cv::COLOR_RGBA2RGB);

もまた間違っていると見えます.

投稿2021/12/02 09:22

fana

総合スコア11654

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

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

sterengers

2021/12/03 01:16

すいません、使う物を間違えてました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問