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

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

ただいまの
回答率

89.55%

リアルタイムエッジ検出

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,738

kotetu

score 32

閲覧有難うございます。

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

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

////////////////////////////////////////////////////
  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);

  //////////////////////////////////////////

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

#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
static void help()
{  
cout<<"Program build!!!! "<<CV_VERSION<< "\n"<<endl;
}
void detectAndDraw( Mat& img, CascadeClassifier& cascade,
                    CascadeClassifier& nestedCascade,
                    double scale, bool tryflip );
string cascadeName;
string nestedCascadeName;
int main(int argc, const char** argv)
{
  VideoCapture capture;

  Mat frame, image;
  string inputName;
  bool tryflip;
  help();
  CascadeClassifier cascade, nestedCascade;
  double scale;

  ////////////////////////////////////////////////////
  上記のコードの場所
  //////////////////////////////////////////

  cv::CommandLineParser parser(argc, argv,
                   "{help h||}{scale|1|}"
                   "{cascade|../../data/haarcascades/haarcascade_frontalface_alt.xml|}"
                   "{smile-cascade|../../data/haarcascades/haarcascade_smile.xml|}"
                   "{try-flip||}{@input||}");
  if (parser.has("help"))
    {
      help();
      return 0;
    }

  cascadeName = parser.get<string>("cascade");
  nestedCascadeName = parser.get<string>("smile-cascade");
  tryflip = parser.has("try-flip");
  inputName = parser.get<string>("@input");
  scale = parser.get<int>("scale");
  if (!parser.check())
    {
      help();
      return 1;
    }
  if (scale < 1)
    scale = 1;
  if( !cascade.load( cascadeName ) )
    {
      cerr << "ERROR: Could not load face cascade" << endl;
      help();
      return -1;
    }
  if( !nestedCascade.load( nestedCascadeName ) )
    {
      cerr << "ERROR: Could not load smile cascade" << endl;
      help();
      return -1;
    }
  if( inputName.empty() || (isdigit(inputName[0]) && inputName.size() == 1) )
    {
      int c = inputName.empty() ? 0 : inputName[0] - '0' ;
      if(!capture.open(c))
    cout << "Capture from camera #" <<  c << " didn't work" << endl;
    }
  else if( inputName.size() )
    {
      if(!capture.open( inputName ))
    cout << "Could not read " << inputName << endl;
    }
  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 );
      char c = (char)waitKey(10);
      if( c == 27 || c == 'q' || c == 'Q' )
        {
          break;
        }
    }
    }
  else
    {
      cerr << "ERROR: Could not initiate capture" << endl;
      help();
      return -1;
    }
  return 0;
}
void detectAndDraw( Mat& img, CascadeClassifier& cascade,
             CascadeClassifier& nestedCascade,
            double scale, bool tryflip)
{
  vector<Rect> faces, faces2;
  const static Scalar colors[] =
    {
      Scalar(255,0,0),
      Scalar(255,128,0),
      Scalar(255,255,0),
      Scalar(0,255,0),
      Scalar(0,128,255),
      Scalar(0,255,255),
      Scalar(0,0,255),
      Scalar(255,0,255)
    };
  Mat gray, smallImg;
  cvtColor( img, gray, COLOR_BGR2GRAY );
  double fx = 1 / scale;
  resize( gray, smallImg, Size(), fx, fx, INTER_LINEAR );
  equalizeHist( smallImg, smallImg );
  cascade.detectMultiScale( smallImg, faces,
                1.1, 2, 0
                //|CASCADE_FIND_BIGGEST_OBJECT
                //|CASCADE_DO_ROUGH_SEARCH
                |CASCADE_SCALE_IMAGE,
                Size(30, 30) );
  if( tryflip )
    {
      flip(smallImg, smallImg, 1);
        cascade.detectMultiScale( smallImg, faces2,
                  1.5, 2, 0
                  //|CASCADE_FIND_BIGGEST_OBJECT
                  //|CASCADE_DO_ROUGH_SEARCH
                  |CASCADE_SCALE_IMAGE,
                  Size(30, 30) );
        for( vector<Rect>::const_iterator r = faces2.begin(); r != faces2.end(); ++r )
      {
            faces.push_back(Rect(smallImg.cols - r->x - r->width, r->y, r->width, r->height));
      }
    }
  for ( size_t i = 0; i < faces.size(); i++ )
    {
      Rect r = faces[i];
      Mat smallImgROI;
      vector<Rect> nestedObjects;
      Point center;
      Scalar color = colors[i%8];
      int radius;
      int face[] = {cv::FONT_HERSHEY_SIMPLEX, cv::FONT_HERSHEY_PLAIN, cv::FONT_HERSHEY_DUPLEX, cv::FONT_HERSHEY_COMPLEX, 
            cv::FONT_HERSHEY_TRIPLEX, cv::FONT_HERSHEY_COMPLEX_SMALL, cv::FONT_HERSHEY_SCRIPT_SIMPLEX, 
            cv::FONT_HERSHEY_SCRIPT_COMPLEX, cv::FONT_ITALIC};
      double aspect_ratio = (double)r.width/r.height;
      if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
        {
      center.x = cvRound((r.x + r.width*0.5)*scale);
      center.y = cvRound((r.y + r.height*0.5)*scale);
      radius = cvRound((r.width + r.height)*0.25*scale);
      circle( img, center, radius, color, 3, 8, 0 );

        }
      else
    rectangle( img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)),
           cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),color, 3, 8, 0);
      const int half_height=cvRound((float)r.height/2);
      r.y=r.y + half_height;
      r.height = half_height-1;
      smallImgROI = smallImg( r );
      nestedCascade.detectMultiScale( smallImgROI, nestedObjects,
                      1.1, 0, 0
                      //|CASCADE_FIND_BIGGEST_OBJECT
                      //|CASCADE_DO_ROUGH_SEARCH
                      //|CASCADE_DO_CANNY_PRUNING
                      |CASCADE_SCALE_IMAGE,
                      Size(30, 30) );
      // The number of detected neighbors depends on image size (and also illumination, etc.). The
      // following steps use a floating minimum and maximum of neighbors. Intensity thus estimated will be
      //accurate only after a first smile has been displayed by the user.
      const int smile_neighbors = (int)nestedObjects.size();
      static int max_neighbors=-1;
      static int min_neighbors=-1;
      if (min_neighbors == -1)
        min_neighbors = smile_neighbors;
      max_neighbors = MAX(max_neighbors, smile_neighbors);
      // Draw rectangle on the left side of the image reflecting smile intensity
      float intensityZeroOne = ((float)smile_neighbors - min_neighbors) / (max_neighbors - min_neighbors + 1);
      //(現在の笑顔-笑顔の最小値)/(笑顔の最大値 - 笑顔の最小値 + 1)
    double rect_height = cvRound((float)img.rows* intensityZeroOne)/2;
    char rectchar[256];
    char maxsmile[256];
    char minsmile[256];
    Scalar col = Scalar((float)255 * intensityZeroOne, 0, 0);
    sprintf(rectchar, "%f", rect_height);//対応しているのはdouble型
    sprintf(maxsmile, "%d", max_neighbors);//対応しているのはint型
    sprintf(minsmile, "%d", min_neighbors);//対応しているのはint型

    //greenline
    line(img,Point(0,240), Point(70,240), Scalar(0,200,0), 5, CV_AA);

    //上から笑顔度、笑顔度の最大値、笑顔度の最小値、現在の笑顔度
    putText(img, "smile", cvPoint(488,30), face[2], 0.5, cvScalar(0,0,200), 1, CV_AA);
    putText(img, "degree", cvPoint(478,50), face[2], 0.5, cvScalar(0,0,200), 1, CV_AA);
    putText(img, "MAX", cvPoint(488,75), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA);
    putText(img, maxsmile, cvPoint(540,75), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA);
    putText(img, "MIN", cvPoint(488,95), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA);
    putText(img, minsmile, cvPoint(540,95), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA);
    //putText(img, imgrow, cvPoint(540,115), face[3], 0.8, cvScalar(0,0,200), 1, CV_AA);

    if(rect_height>0)
      {
    rectangle(img, cvPoint(0, 235), cvPoint(img.cols/10, 240-rect_height), CV_RGB(200,0,0), CV_FILLED);
    putText(img, "GOOD", cvPoint(535,50), face[0], 1.2, cv::Scalar(0,0,200), 2, CV_AA);
      }
    else
      {
    rectangle(img, cvPoint(0,245), cvPoint(img.cols/10,240-rect_height), CV_RGB(0,0,200), CV_FILLED);
    putText(img, "BAD", cvPoint(535,50), face[0], 1.2, cv::Scalar(0,0,200), 2, CV_AA);
      }
    }
  imshow( "result", img );
}


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

  • 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
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

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

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

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

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

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

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • episteme

    2018/02/10 20:58

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

    キャンセル

回答 2

check解決した方法

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()の所に処理を書くことですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/11 17:20

    はい、そのです。

    キャンセル

  • 2018/02/11 17:43

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

    キャンセル

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

  • ただいまの回答率 89.55%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

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