0

I am doing a Matching Contours test.

Here I use image called "refshape.bmp" (link: https://www.dropbox.com/s/06hrjji49uyid4w/refshape.bmp?dl=0) And image called "2.bmp" (link: https://www.dropbox.com/s/5t73mvbdfbtqvs1/2.BMP?dl=0)

to do this test.

This code is following: I have two part of this code Part 1: rotate the "refshape.bmp" image Part 2: Matching Contours with a red line. (the separate part can work successfully! ) But I have a problem with convert between CV Mat and IplImage.

There is the overflow warning: link: www.dropbox.com/s/mne4u3va94svx8y/%E6%93%B7%E5%8F%96.JPG?dl=0

First part there is a CV mat (image) "dst" then I convert it to IplImage by: "IplImage* reference= ©" "IplImage* reference= ©"

#include <stdlib.h>
#include<iostream>
#include "time.h"
#include "highgui.h"
#include "cv.h"

using namespace std;

int comp(const void *p,const void *q)
{
   return (*(int *)p - *(int *)q);
}




int main()

{   int i =0;
    cv::Mat src = cv::imread("refshape.bmp", CV_LOAD_IMAGE_UNCHANGED);
    int angle = -i;

    // get rotation matrix for rotating the image around its center
    cv::Point2f center(src.cols/2.0, src.rows/2.0);
    cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
    // determine bounding rectangle
    cv::Rect bbox = cv::RotatedRect(center,src.size(), angle).boundingRect();
    // adjust transformation matrix
    rot.at<double>(0,2) += bbox.width/2.0 - center.x;
    rot.at<double>(1,2) += bbox.height/2.0 - center.y;

    cv::Mat dst;
    cv::warpAffine(src, dst, rot, bbox.size());
 IplImage copy = dst;



 IplImage* input = NULL;
 IplImage* input_canny = NULL;
 IplImage* input_final = NULL;
 //IplImage* reference = NULL;
 IplImage* input_gray = NULL;
 IplImage* reference_gray = NULL;
 IplImage* find_contour = NULL;

 IplImage* reference= &copy;

 //圖像的尺寸的寬度大小
 int x_min = 229;               
 int x_max = 0;

 //圖像尺寸的高度大小
 int y_min = 111;
 int y_max = 0;
 
 int n = 0;  

 //reference = cvLoadImage("refshape.bmp",1);//讀取圖檔
 input = cvLoadImage("2.bmp",1);//讀取圖檔

 input_canny=cvCreateImage(cvSize(input->width, input->height),  IPL_DEPTH_8U,1);//canny灰階

 input_final=cvCreateImage(cvSize(input->width, input->height),  IPL_DEPTH_8U,3);//canny RGB

 cvCvtColor(input, input_canny, CV_BGR2GRAY);//轉灰階圖
 
 cvCanny(input_canny,input_canny,80,150,3);// canny edge

 cvCvtColor(input_canny, input_final, CV_GRAY2BGR);// canny 灰階轉RGB
 

 reference_gray = cvCreateImage(cvSize(reference->width, reference->height),  IPL_DEPTH_8U,1);
 input_gray = cvCreateImage(cvSize(input->width, input->height),  IPL_DEPTH_8U,1);

 CvMemStorage* storage = cvCreateMemStorage(0);
 CvSeq *contour = 0;

 //cvFindContours只能使用灰階影像,故須先轉成灰階
 cvCvtColor(reference, reference_gray, CV_BGR2GRAY);

 cvFindContours(reference_gray, storage, &contour, sizeof(CvContour), CV_RETR_LIST , CV_CHAIN_APPROX_NONE, cvPoint(0,0));

 //用來存放點的位置矩陣
 CvPoint* PointArray[50000]={0};



 //以下是將每一層的每個點的位置座標,存到PointArray裡,並且找出所有sample點x,y軸的最大最小值
 for( CvSeq* c = contour; c != NULL; c=c->h_next )
    {
        for( int i = 0; i<c->total; i++ )
  {
   
   PointArray[n] = CV_GET_SEQ_ELEM( CvPoint, c, i );

   if(PointArray[n]->x < x_min)
   {
    x_min = PointArray[n]->x;
   }
   
   if(PointArray[n]->y < y_min)
   {
    y_min = PointArray[n]->y;
   }

   if(PointArray[n]->x > x_max)
   {
    x_max = PointArray[n]->x;
   }

   if(PointArray[n]->y > y_max)
   {
    y_max = PointArray[n]->y;
   }

   n+=1;
  }
    }
    

 CvScalar s,t;
 int match_x;
 int match_y;

// Contour matching

 int x;
 int y;
 int matchcount=0;
 int maxcount=0;

 for(int i=0;i<780;i++)
 {
  for(int j=0;j<630;j++)
  { 
   matchcount=0;
   for(int a = 0; a < n; a++)
   {
    s = cvGet2D(input_final, PointArray[a]->y -y_min+j, PointArray[a]->x -x_min+i);
    t = cvGet2D(reference,PointArray[a]->y,PointArray[a]->x);
            
    if(s.val[0]==255 && t.val[0]==255)
     matchcount++;
   }
   if(matchcount>maxcount)
   {
    maxcount=matchcount;
    match_x =i ;
    match_y =j ;
   }
  }
 }
      
 system("pause");
 //當找到match數最多的位置時,設定要畫出的顏色後,將這些點標上顏色
 for(int a = 0; a < n; a++)
 {
  t.val[0] = 0;
  t.val[1] = 0;
  t.val[2] = 255;

  //標上顏色
  cvSet2D(input_final, PointArray[a]->y-y_min+match_y, PointArray[a]->x-x_min+match_x, t);
 }

 system("pause");
 cvNamedWindow("reference_gray",1);
 cvNamedWindow("reference",1);
 cvNamedWindow("input",1);
 cvShowImage("reference_gray",reference_gray);
 cvShowImage("reference",reference);
 cvShowImage("input",input_final);
 
 cvSaveImage("result.bmp",input_final);
 system("pause");
 cvWaitKey(0);

    return 0;
}

There are separate code: Rotation:

#include "opencv2/opencv.hpp"
#include <sstream>

int main()
{ for (int i=0;i<361;i++)
{
    cv::Mat src = cv::imread("refshape.bmp", CV_LOAD_IMAGE_UNCHANGED);
    int angle = -i;

    // get rotation matrix for rotating the image around its center
    cv::Point2f center(src.cols/2.0, src.rows/2.0);
    cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
    // determine bounding rectangle
    cv::Rect bbox = cv::RotatedRect(center,src.size(), angle).boundingRect();
    // adjust transformation matrix
    rot.at<double>(0,2) += bbox.width/2.0 - center.x;
    rot.at<double>(1,2) += bbox.height/2.0 - center.y;

    cv::Mat dst;
    cv::warpAffine(src, dst, rot, bbox.size());

    std::ostringstream name;
    name << "rotated_im_" << i << ".png";
    cv::imwrite(name.str(), dst);
}
    return 0;
}

There is Matching Contours code:

#include <stdlib.h>
#include<iostream>
#include "time.h"
#include "highgui.h"
#include "cv.h"

using namespace std;

int comp(const void *p,const void *q)
{
   return (*(int *)p - *(int *)q);
}

int main()
{
 IplImage* input = NULL;
 IplImage* input_canny = NULL;
 IplImage* input_final = NULL;
 IplImage* reference = NULL;
 IplImage* input_gray = NULL;
 IplImage* reference_gray = NULL;
 IplImage* find_contour = NULL;

 //圖像的尺寸的寬度大小
 int x_min = 229;               
 int x_max = 0;

 //圖像尺寸的高度大小
 int y_min = 111;
 int y_max = 0;
 
 int n = 0;  

 reference = cvLoadImage("refshape.bmp",1);//讀取圖檔
 input = cvLoadImage("2.bmp",1);//讀取圖檔

 input_canny=cvCreateImage(cvSize(input->width, input->height),  IPL_DEPTH_8U,1);//canny灰階

 input_final=cvCreateImage(cvSize(input->width, input->height),  IPL_DEPTH_8U,3);//canny RGB

 cvCvtColor(input, input_canny, CV_BGR2GRAY);//轉灰階圖
 
 cvCanny(input_canny,input_canny,80,150,3);// canny edge

 cvCvtColor(input_canny, input_final, CV_GRAY2BGR);// canny 灰階轉RGB
 

 reference_gray = cvCreateImage(cvSize(reference->width, reference->height),  IPL_DEPTH_8U,1);
 input_gray = cvCreateImage(cvSize(input->width, input->height),  IPL_DEPTH_8U,1);

 CvMemStorage* storage = cvCreateMemStorage(0);
 CvSeq *contour = 0;

 //cvFindContours只能使用灰階影像,故須先轉成灰階
 cvCvtColor(reference, reference_gray, CV_BGR2GRAY);

 cvFindContours(reference_gray, storage, &contour, sizeof(CvContour), CV_RETR_LIST , CV_CHAIN_APPROX_NONE, cvPoint(0,0));

 //用來存放點的位置矩陣
 CvPoint* PointArray[5000]={0};



 //以下是將每一層的每個點的位置座標,存到PointArray裡,並且找出所有sample點x,y軸的最大最小值
 for( CvSeq* c = contour; c != NULL; c=c->h_next )
    {
        for( int i = 0; i<c->total; i++ )
  {
   
   PointArray[n] = CV_GET_SEQ_ELEM( CvPoint, c, i );

   if(PointArray[n]->x < x_min)
   {
    x_min = PointArray[n]->x;
   }
   
   if(PointArray[n]->y < y_min)
   {
    y_min = PointArray[n]->y;
   }

   if(PointArray[n]->x > x_max)
   {
    x_max = PointArray[n]->x;
   }

   if(PointArray[n]->y > y_max)
   {
    y_max = PointArray[n]->y;
   }

   n+=1;
  }
    }
    

 CvScalar s,t;
 int match_x;
 int match_y;

// Contour matching

 int x;
 int y;
 int matchcount=0;
 int maxcount=0;

 for(int i=0;i<780;i++)
 {
  for(int j=0;j<630;j++)
  { 
   matchcount=0;
   for(int a = 0; a < n; a++)
   {
    s = cvGet2D(input_final, PointArray[a]->y -y_min+j, PointArray[a]->x -x_min+i);
    t = cvGet2D(reference,PointArray[a]->y,PointArray[a]->x);
            
    if(s.val[0]==255 && t.val[0]==255)
     matchcount++;
   }
   if(matchcount>maxcount)
   {
    maxcount=matchcount;
    match_x =i ;
    match_y =j ;
   }
  }
 }
      
 system("pause");
 //當找到match數最多的位置時,設定要畫出的顏色後,將這些點標上顏色
 for(int a = 0; a < n; a++)
 {
  t.val[0] = 0;
  t.val[1] = 0;
  t.val[2] = 255;

  //標上顏色
  cvSet2D(input_final, PointArray[a]->y-y_min+match_y, PointArray[a]->x-x_min+match_x, t);
 }

 system("pause");
 cvNamedWindow("reference_gray",1);
 cvNamedWindow("reference",1);
 cvNamedWindow("input",1);
 cvShowImage("reference_gray",reference_gray);
 cvShowImage("reference",reference);
 cvShowImage("input",input_final);
 
 cvSaveImage("result.bmp",input_final);
 system("pause");
 cvWaitKey(0);
}
  • There is the overflow warning: https://www.dropbox.com/s/mne4u3va94svx8y/%E6%93%B7%E5%8F%96.JPG?dl=0 – Hsu Yu-Wei Auston Dec 11 '14 at 08:55
  • please just avoid using IplImages. the c-api is deprecated / no more maintained. they moved to c++ 5 years ago. – berak Dec 11 '14 at 09:09
  • @berak But my sample code from school using...Deadline of this test will be in 5 hours. Does there have any suggestions with IplImage? – Hsu Yu-Wei Auston Dec 11 '14 at 09:16
  • 1
    if you really have to use the C-API you should not use `cv::Mat` `cv::Rect` etc but just use C-API all the way. So change `cv::Mat src = cv::imread` to `CvMat` or `cvMat` and the `cvLoadImage` equivalent. Change `cv::getRotationMatrix2D` to `cv2DRotationMatrix` etc etc – Micka Dec 11 '14 at 09:28
  • 1
    and/or make clear WHERE in your code you have problems in converting `cv::Mat` to `IplImage` because I dont find it and am too lazy to search ;) – Micka Dec 11 '14 at 09:32
  • use boundingRect() and matchContours() (or their c equiv.) instead of your loops – berak Dec 11 '14 at 09:39
  • @Micka There is the overflow warning: link: www.dropbox.com/s/mne4u3va94svx8y/%E6%93%B7%E5%8F%96.JPG?dl=0 – Hsu Yu-Wei Auston Dec 11 '14 at 10:47
  • if you got errors, paste the *text* here, not a link to a picture, please. also, you got a maintenance *hell* there, complexity is your main enemy. reduce it as far as possible, prefer builtin functions to per-pixel loops. – berak Dec 11 '14 at 10:48
  • Which of the code snippets is the relevant one? first second or third?? in your first code part: `cv::Mat dst; IplImage copy = dst;` does not make much sense since `dst` is empty there. So later `dst` probably gets data allocated, but `copy` doesnt. Edit: in your first code snippet, `dst` never gets any data?!? – Micka Dec 11 '14 at 10:58
  • @Micka The First code; The Second and The Third codes are referenced code. I combined them to The First code. Sorry, I missed this line of code "cv::warpAffine(src, dst, rot, bbox.size());" – Hsu Yu-Wei Auston Dec 11 '14 at 11:17
  • your conversion (`IplImage copy = dst;` followed by `IplImage* reference= ©`) seems to be ok, so there might be another fault... – Micka Dec 11 '14 at 12:21

0 Answers0