cv2.0 入门

OpenCV轮廓检测,计算物体旋转角度


  
#include "stdafx.h"  
  
  
  
#include <iostream>  
#include <vector>  
#include <opencv2/opencv.hpp>   
#include <opencv2/core/core.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/highgui/highgui.hpp>  
  
  
  
  
#define PI 3.1415926  
  
using namespace std;  
using namespace cv;  
  
  
  
int hough_line(Mat src)  
{  
    //【1】载入原始图和Mat变量定义     
    Mat srcImage = src;//imread("1.jpg");  //工程目录下应该有一张名为1.jpg的素材图  
    Mat midImage,dstImage;//临时变量和目标图的定义  
  
    //【2】进行边缘检测和转化为灰度图  
    Canny(srcImage, midImage, 50, 200, 3);//进行一此canny边缘检测  
    cvtColor(midImage,dstImage, CV_GRAY2BGR);//转化边缘检测后的图为灰度图  
  
    //【3】进行霍夫线变换  
    vector<Vec4i> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合  
    HoughLinesP(midImage, lines, 1, CV_PI/180, 80, 50, 10 );  
  
    //【4】依次在图中绘制出每条线段  
    for( size_t i = 0; i < lines.size(); i++ )  
    {  
        Vec4i l = lines[i];  
        line( dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(186,88,255), 1, CV_AA);  
    }  
  
    //【5】显示原始图    
    imshow("【原始图】", srcImage);    
  
    //【6】边缘检测后的图   
    imshow("【边缘检测后的图】", midImage);    
  
    //【7】显示效果图    
    imshow("【效果图】", dstImage);    
  
    //waitKey(0);    
  
    return 0;    
}  
  
int main()  
{  
    // Read input binary image  
  
    char *image_name = "c:\\img\\1.bmp";  
    cv::Mat image = cv::imread(image_name,0);  
    if (!image.data)  
        return 0;   
  
    cv::namedWindow("Binary Image");  
    cv::imshow("Binary Image",image);  
  
  
      
    // 从文件中加载原图    
       IplImage *pSrcImage = cvLoadImage(image_name, CV_LOAD_IMAGE_UNCHANGED);    
        
           // 转为2值图  
          
     cvThreshold(pSrcImage,pSrcImage,200,255,cv::THRESH_BINARY_INV);  
             
      
       image = cv::Mat(pSrcImage,true);  
  
       cv::imwrite("binary.jpg",image);  
  
    // Get the contours of the connected components  
    std::vector<std::vector<cv::Point>> contours;  
    cv::findContours(image,   
        contours, // a vector of contours   
        CV_RETR_EXTERNAL, // retrieve the external contours  
        CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours  
  
    // Print contours' length  
    std::cout << "Contours: " << contours.size() << std::endl;  
    std::vector<std::vector<cv::Point>>::const_iterator itContours= contours.begin();  
    for ( ; itContours!=contours.end(); ++itContours)   
    {  
  
        std::cout << "Size: " << itContours->size() << std::endl;  
    }  
  
    // draw black contours on white image  
    cv::Mat result(image.size(),CV_8U,cv::Scalar(255));  
    cv::drawContours(result,contours,  
        -1, // draw all contours  
        cv::Scalar(0), // in black  
        2); // with a thickness of 2  
  
    cv::namedWindow("Contours");  
    cv::imshow("Contours",result);  
  
  
  
  
  
  
    // Eliminate too short or too long contours  
    int cmin= 100;  // minimum contour length  
    int cmax= 1000; // maximum contour length  
    std::vector<std::vector<cv::Point>>::const_iterator itc= contours.begin();  
    while (itc!=contours.end()) {  
  
        if (itc->size() < cmin || itc->size() > cmax)  
            itc= contours.erase(itc);  
        else   
            ++itc;  
    }  
  
    // draw contours on the original image  
    cv::Mat original= cv::imread(image_name);  
    cv::drawContours(original,contours,  
        -1, // draw all contours  
        cv::Scalar(255,255,0), // in white  
        2); // with a thickness of 2  
  
    cv::namedWindow("Contours on original");  
    cv::imshow("Contours on original",original);  
  
      
  
    // Let's now draw black contours on white image  
    result.setTo(cv::Scalar(255));  
    cv::drawContours(result,contours,  
        -1, // draw all contours  
        cv::Scalar(0), // in black  
        1); // with a thickness of 1  
    image= cv::imread("binary.jpg",0);  
  
    //imshow("lll",result);  
    //waitKey(0);  
  
    // testing the bounding box   
    //////////////////////////////////////////////////////////////////////////////  
    //霍夫变换进行直线检测,此处使用的是probabilistic Hough transform(cv::HoughLinesP)而不是standard Hough transform(cv::HoughLines)  
  
    cv::Mat result_line(image.size(),CV_8U,cv::Scalar(255));  
    result_line = result.clone();  
  
    hough_line(result_line);  
  
    //Mat tempimage;  
  
    //【2】进行边缘检测和转化为灰度图  
    //Canny(result_line, tempimage, 50, 200, 3);//进行一此canny边缘检测  
    //imshow("canny",tempimage);  
    //waitKey(0);  
  
    //cvtColor(tempimage,result_line, CV_GRAY2BGR);//转化边缘检测后的图为灰度图  
    vector<Vec4i> lines;  
  
    cv::HoughLinesP(result_line,lines,1,CV_PI/180,80,50,10);  
  
    for(int i = 0; i < lines.size(); i++)  
    {  
        line(result_line,cv::Point(lines[i][0],lines[i][1]),cv::Point(lines[i][2],lines[i][3]),Scalar(0,0,0),2,8,0);  
    }  
    cv::namedWindow("line");  
    cv::imshow("line",result_line);  
    //waitKey(0);  
  
    /////////////////////////////////////////////////////////////////////////////////////////////  
    //  
  
    //std::vector<std::vector<cv::Point>>::const_iterator itc_rec= contours.begin();  
    //while (itc_rec!=contours.end())  
    //{  
    //  cv::Rect r0= cv::boundingRect(cv::Mat(*(itc_rec)));  
    //  cv::rectangle(result,r0,cv::Scalar(0),2);  
    //      ++itc_rec;  
    //}  
  
      
  
    //cv::namedWindow("Some Shape descriptors");  
    //cv::imshow("Some Shape descriptors",result);  
  
  
    CvBox2D     End_Rage2D;  
    CvPoint2D32f rectpoint[4];  
    CvMemStorage *storage = cvCreateMemStorage(0);  //开辟内存空间  
  
  
    CvSeq*      contour = NULL;     //CvSeq类型 存放检测到的图像轮廓边缘所有的像素值,坐标值特征的结构体以链表形式  
  
    cvFindContours( pSrcImage, storage, &contour, sizeof(CvContour),CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);//这函数可选参数还有不少  
  
  
  
    for(; contour; contour = contour->h_next)   //如果contour不为空,表示找到一个以上轮廓,这样写法只显示一个轮廓  
        //如改为for(; contour; contour = contour->h_next) 就可以同时显示多个轮廓  
    {    
  
        End_Rage2D = cvMinAreaRect2(contour);    
        //代入cvMinAreaRect2这个函数得到最小包围矩形  这里已得出被测物体的角度,宽度,高度,和中点坐标点存放在CvBox2D类型的结构体中,  
        //主要工作基本结束。  
        for(int i = 0;i< 4;i++)  
        {  
              //CvArr* s=(CvArr*)&result;  
            //cvLine(s,cvPointFrom32f(rectpoint[i]),cvPointFrom32f(rectpoint[(i+1)%4]),CV_G(0,0,255),2);  
            line(result,cvPointFrom32f(rectpoint[i]),cvPointFrom32f(rectpoint[(i+1)%4]),Scalar(125),2);  
        }   
        cvBoxPoints(End_Rage2D,rectpoint);  
      
    std::cout <<" angle:\n"<<(float)End_Rage2D.angle << std::endl;      //被测物体旋转角度   
      
    }  
    cv::imshow("lalalal",result);  
    cv::waitKey();  
    return 0;  
  
  
}  

提取连通区域轮廓


#include <iostream>  
#include <opencv2\core\core.hpp>  
#include <opencv2\highgui\highgui.hpp>  
#include <opencv2\imgproc\imgproc.hpp>  
  
using namespace std;  
using namespace cv;  


// 移除过小或过大的轮廓  
void getSizeContours(vector<vector<Point>> &contours)  
{  
    int cmin = 100;   // 最小轮廓长度  
    int cmax = 1000;   // 最大轮廓长度  
    vector<vector<Point>>::const_iterator itc = contours.begin();  
    while(itc != contours.end())  
    {  
        if((itc->size()) < cmin || (itc->size()) > cmax)  
        {  
            itc = contours.erase(itc);  
        }  
        else ++ itc;  
    }  
}  
  
// 计算连通区域的轮廓,即二值图像中相连像素的形状  
  
int main()  
{  
    Mat image = imread("c:\\img\\1.bmp",0);  
    if(!image.data)  
    {  
        cout << "Fail to load image" << endl;  
        return 0;  
    }  
    Mat imageShold;  
    threshold(image, imageShold, 100, 255, THRESH_BINARY);   // 必须进行二值化  
    vector<vector<Point>> contours;  
    //CV_CHAIN_APPROX_NONE  获取每个轮廓每个像素点  
    findContours(imageShold, contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0));  
    getSizeContours(contours);  
    cout << contours.size() << endl;  
    Mat result(image.size(), CV_8U, Scalar(255));  
    drawContours(result, contours, -1, Scalar(0), 2);   // -1 表示所有轮廓  
    namedWindow("result");  
    imshow("result", result);  
    namedWindow("image");  
    imshow("image", image);  
    waitKey(0);  
    return 0;  
}  

计算连通区域数目与最大连通区域并标示出


    #include <stdio.h>  
    #include <cv.h>  
    #include <highgui.h>  
      
     
      
    int main( int argc, char** argv )    
    {  
        IplImage* src = cvLoadImage("c:\\img\\1.png", CV_LOAD_IMAGE_GRAYSCALE);  
        IplImage* dst = cvCreateImage(cvGetSize(src), 8, 3);  
        CvMemStorage* storage = cvCreateMemStorage(0);  
        CvSeq* contour = 0;  
        cvThreshold(src, src,120, 255, CV_THRESH_BINARY);   // 二值化  
        cvNamedWindow("Source", 1);  
        cvShowImage("Source", src);  
        // 提取轮廓  
        int contour_num = cvFindContours(src, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);  
        cvZero(dst);        // 清空数组  
        CvSeq *_contour = contour;   
        double maxarea = 0;  
        double minarea = 100;  
        int m = 0;  
        for( ; contour != 0; contour = contour->h_next )    
        {    
      
            double tmparea = fabs(cvContourArea(contour));  
            if(tmparea < minarea)     
            {    
                cvSeqRemove(contour, 0); // 删除面积小于设定值的轮廓  
                continue;  
            }    
            CvRect aRect = cvBoundingRect( contour, 0 );   
            if ((aRect.width/aRect.height)<1)    
            {    
                cvSeqRemove(contour, 0); //删除宽高比例小于设定值的轮廓  
                continue;  
            }    
            if(tmparea > maxarea)    
            {    
                maxarea = tmparea;  
            }    
            m++;  
            // 创建一个色彩值  
            CvScalar color = CV_RGB( 0, 255, 255 );  
      
            //max_level 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓  
            //如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种  
            //如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓  
            cvDrawContours(dst, contour, color, color, -1, 1, 8);   //绘制外部和内部的轮廓  
        }    
        contour = _contour;  
        int count = 0;  
        for(; contour != 0; contour = contour->h_next)  
        {    
            count++;  
            double tmparea = fabs(cvContourArea(contour));  
            if (tmparea == maxarea)    
            {    
                CvScalar color = CV_RGB( 255, 0, 0);  
                cvDrawContours(dst, contour, color, color, -1, 1, 8);  
            }    
        }    
        printf("The total number of contours is:%d", count);  
        cvNamedWindow("Components", 1);  
        cvShowImage("Components", dst);  
        cvWaitKey(0);  
        cvDestroyWindow("Source");  
        cvReleaseImage(&src);  
        cvDestroyWindow("Components");  
        cvReleaseImage(&dst);  
      
        return 0;  
    }    

opencv 显示最小面积的外接矩形,并求该矩形的长和宽以及四个角的位置


#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <math.h>
int main(int argc,char argv)
{
 IplImage *src,*gray,*bw,*dst;
    CvMemStorage* storage=cvCreateMemStorage(0);
 CvSeq* contour=0;
 
 char* filename= "c:\\img\\1.png";
  
 if(!filename)
  printf("can't open the file:%d\n",filename);
   
 src=cvLoadImage(filename,1);

  cvNamedWindow("image",1);
  cvShowImage("image",src);

    gray=cvCreateImage(cvSize(src->width,src->height),src->depth,1);
 cvCvtColor(src,gray,CV_BGR2GRAY);
 int hei,wid;
    hei=gray->height;//注意此处是gray,otsu中要用到hei,wid,已在otsu.h中全局定义;
 wid=gray->width;
 printf("图像的高为:%d,宽为:%d\n\n",hei,wid);

  cvNamedWindow("image2",1);
     cvShowImage("image2",gray);


    bw=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
      cvThreshold(gray,bw,128,255,CV_THRESH_BINARY_INV);

 
    cvNamedWindow("image4",1);
  cvShowImage("image4",bw);


  dst=cvCloneImage(src);
  cvFindContours(bw,storage,&contour,sizeof(CvContour),CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE);
 for(;contour!=0;contour=contour->h_next)

 { CvBox2D rect=cvMinAreaRect2(contour,storage);

  CvPoint2D32f rect_pts0[4];
  cvBoxPoints(rect, rect_pts0);//在c++中已经被废除。

//因为cvPolyLine要求点集的输入类型是CvPoint
//所以要把 CvPoint2D32f 型的 rect_pts0 转换为 CvPoint 型的 rect_pts
//并赋予一个对应的指针 *pt
int npts = 4,k=0;
int aaa=0,bbb=0;
CvPoint rect_pts[4], *pt = rect_pts;

printf("连通区域最小外接矩形顶点坐标分别为:\n");
for (int i=0; i<4; i++)
{
 rect_pts[i]= cvPointFrom32f(rect_pts0[i]);
  printf("%d %d\n",rect_pts[i].x,rect_pts[i].y);
  aaa=(int)sqrt((pow((float)(rect_pts[0].x-rect_pts[1].x),2)+pow((float)(rect_pts[0].y-rect_pts[1].y),2)));
  bbb=(int)sqrt((pow((float)(rect_pts[0].x-rect_pts[3].x),2)+pow((float)(rect_pts[0].y-rect_pts[3].y),2)));

   if(aaa<bbb)
    {
     k=aaa;
     aaa=bbb;
     bbb=k;
    }

}
printf("最小外接矩形的长为:%d,宽为:%d。\n\n",aaa,bbb);
cvPolyLine(dst, &pt, &npts, 1, 1, CV_RGB(255,0,0), 1);
 }
 cvNamedWindow("image5",1);
  cvShowImage("image5",dst);

  cvWaitKey(0);//注意此句放的位置,放的不对则。。。
  
cvDestroyWindow("image");
cvDestroyWindow("image2");
cvDestroyWindow("image4");
cvDestroyWindow("image5");

cvReleaseImage(&src);
cvReleaseImage(&gray);
cvReleaseImage(&bw);
cvReleaseImage(&dst);
  
  return 0;
}

 

数字分割

#include "stdafx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "iostream"
#include <vector>
 
using namespace std;

CvRect CutTopButtom(IplImage *src);
vector<CvRect>leftright;
//vector<CvRect>::iterator iter;
int lstart=0,lend=0,lrun=0;
int lastStart=0,lastEnd=0;
IplImage *dst[10];
CvRect rectRoi;


void FindLeftRight(IplImage *src);
void RememberLeftRight(IplImage *src,int lstart,int lend);
void ShowAndCut(IplImage  *src[]);



IplImage * raw=cvLoadImage("c:\\img\\3.bmp",0);
IplImage * img;

int _tmain(int argc, _TCHAR* argv[])
{   
        cvSmooth(raw,raw);
        cvThreshold(raw,raw,70,255,CV_THRESH_BINARY);
        IplConvKernel *element=0;                                //结构元素
        cvMorphologyEx(raw,raw,NULL,element,CV_MOP_OPEN);        //开运算
        rectRoi=CutTopButtom(raw);
    img=cvCreateImage(cvGetSize(raw),IPL_DEPTH_8U,1);
        cvCopy(raw,img);
        FindLeftRight(raw);
       
       

        return 0;
}


CvRect CutTopButtom(IplImage *src)
{

       
        int* h=new int[src->height];
        memset(h,0,src->height*4);
        int hstart,hend,x,y,zhongdian;  
        CvScalar s;
        for(y=0;y<src->height;y++)  
        {  
                for(x=0;x<src->width;x++)  
                {  
                        s=cvGet2D(src,y,x);           
                        if(s.val[0]==0)  
                                h[y]++;      
                }     
        }
        for (int j=0;j!=src->height;j++)
        {
                if (h[j]>15)
                {
                        zhongdian=j;
                        hstart=zhongdian;
                        break;
                }
                else
                        continue;

        }
        while(zhongdian!=src->height)
        {
                if (h[zhongdian]<10)
                {
                        hend=zhongdian;
                        break;
                }
                else
                        hend=zhongdian;
                zhongdian++;
        }
        CvRect rect=cvRect(0,hstart-10,src->width,hend-hstart+20);
        cvSetImageROI(src,rect);
       
       
        return rect;
}


void FindLeftRight(IplImage *src)
{

        int* v=new int[rectRoi.width];
        memset(v,0,rectRoi.width*4);
        int x,y;  
        CvScalar s;  
        for(x=0;x<rectRoi.width;x++)  
        {  
                for(y=0;y<rectRoi.height;y++)
                {  
                        s=cvGet2D(src,y,x);           
                        if(s.val[0]==0)  
                                v[x]++;  
                        else
                                continue;
                }         
        }
       
        if (lend<=rectRoi.width)  
        {
                for (int i=0;i<rectRoi.width;i++)
                {
                        if(v[i]>10)
                        {
                                lrun=i;
                                lstart=lrun;
                                break;


                        }
                        else
                                continue;
                }
                if (lstart==lrun)
                {
                        for (lrun;lrun<rectRoi.width;lrun++)
                        {
                                if (v[lrun]<5)
                                {
                                        lend=lrun;
                                        break;
                                }
                                else
                                        continue;
                               

                        }
                }
                RememberLeftRight(src,lstart,lend);
        }
       
        else
                ShowAndCut(dst);

       
       
       
}


void RememberLeftRight(IplImage *src,int lstart,int lend)
{
       
        if (lastStart==0&&lastEnd==0)
        {
                lastStart=lastStart+lstart;
                lastEnd=lastEnd+lend;
        }
       
        else
        {
                lastStart=lastEnd+lstart;
                lastEnd=lastEnd+lend;
        }

        CvRect Rect=cvRect(lastStart-10,0,lastEnd-lastStart+20,rectRoi.height);
        //CvRect Rect=cvRect(lastStart-5,0,lend-lstart+15,rectRoi.height);
        leftright.push_back(Rect);
    rectRoi=cvRect(lend,0,(rectRoi.width-lend),rectRoi.height);
        cvSetImageROI(src,rectRoi);
        FindLeftRight(src);
   

}

void ShowAndCut(IplImage *src[])
{
       int i=0;
        for (vector<CvRect>::iterator iter=leftright.begin();iter!=leftright.end();iter++,i++)
        {
                src[i]=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
                cvCopy(img,src[i]);
                cvSetImageROI(src[i],*iter);
                cvNamedWindow("src");
                cvShowImage("src",src[i]);
                cvWaitKey(3000);
               

        }
}


你可能感兴趣的:(cv2.0 入门)