OpenCV学习笔记

目录

一、Mat类

二、VideoCapture类

三、截屏

四、视频条(滑动条)

五、opencv图像的运算

六、图像的通道分离

七、图像滤波

八、转化为灰度图的方法:

九、图像阈值

十、膨胀与腐蚀

十一、基于膨胀腐蚀的其他形态学操作

十二、边缘检测

Canny算子检测:

Sobel算子检测

霍夫线检测

霍夫圆检测

十三、绘制直方图

十四、图像均衡化

十五、图像匹配

单模板匹配

视频匹配

十六、轮廓查找与绘制

十七、访问轮廓的每一个点

十八、轮廓之“点集凸包”

十九、轮廓之“图片凸包”

二十、轮廓之外接矩形的查找与绘制

二十一、最小外接矩形

二十二、点与轮廓的位置关系

二十三、目标查找之轮廓查找

二十四、颜色目标检测

二十五、颜色识别之摄像头三色识别(自己做的)

二十六、分水岭算法

二十七、角点检测

(1)Harris角点检测

(2)goodFeaturesToTrack角点检测

二十八、运动物体目标检测


一、Mat类

Mat image;

image.empty();//判断是否为空

image.rows;//获取图像行数

image.cols;//获取图像列数

image.channels();//获取图像通道数

image.depth();//获取图像位深度

 示例:

# include "ros/ros.h"
# include "opencv2/opencv.hpp"
# include "iostream"

using namespace cv;
using namespace std;

int main(int argc, char const *argv[])
{
    Mat img=imread("/home/zhangpeng/catkin_wstest/me.jpg");
    namedWindow("image",WINDOW_FREERATIO);//可以控制图片显示窗口的大小
    imshow("image",img);
    waitKey(0);//0表示一直等待,如果是1则表示等待1ms后消失
    destroyAllWindows();//表示结束程序后清理所有的窗口
    return 0;
}

二、VideoCapture类

VideoCapture vc;

vc.open();//打开视频文件或者摄像头文件

vc.isOpened();//判断视频是否正确打开

vc.release();//释放视频



int width=vc.get(CV_CAP_PROP_FRAME_WIDTH);//获取帧宽度

int height=vc.get(CV_CAP_PROP_FRAME_HEIGHT);//获取帧高度

int frameRate=vc.get(CV_CAP_PROP_FPS);//获取帧率

int totalFrame=vc.get(CV_CAP_PROP_FRAME_COUNT);//获取总帧率

示例:

读取摄像头:

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 
 
using namespace std;
using namespace cv;
 
int main (void)
{
    VideoCapture cap(0);
    if(!cap.isOpened())
    {
        return -1;
    }
    while (waitKey(1)!=27)
    {
        Mat img;
        cap>>img;
        imshow("image",img);
    }
    waitKey(0);
    return 0;
}

 读取指定的视频:

# include "opencv2/opencv.hpp"

using namespace cv;

int main ()
{
    //视频读取
    VideoCapture cap;
    Size size0=Size(568,320);

    //视频写入
    VideoWrite writer("地址",CV_FOURCC('X','V','I','D'),20,size0,true);//最后一个如果写入彩色就写true否则就写false;如果视频本来就是灰色,则只能写false
    cap.open("视频地址");
    //等价与VideoCapture cap("视频地址");
    if(!cap.isOpened())
    {
        return -1;
    }
    Mat image;
    while(1)
    {
        cap>>image;//取帧方法
        //等价与cap.read(image);
        if(image.empty())
        {
            break;
        }
        writer<

三、截屏

# include "opencv2/opencv.hpp"
# include 
# include "ros/ros.h"

using namespace std;
using namespace cv;

Mat img=imread("/home/zhangpeng/catkin_wsfour/one.jpg");
Mat temp=img.clone();
Mat ROI;
Point pt;
bool flag=false;

void OnMouse(int event,int x,int y,int flag,void* param)
{
    switch(event)
    {
        case CV_EVENT_LBUTTONDOWN://鼠标左键按下
            flag=true;
            pt.x=x;
            pt.y=y;
            break;
        case CV_EVENT_MOUSEMOVE://鼠标移动
            if(flag)
            {
		cout<<"aaaaaa"<

四、视频条(滑动条)

//滑动条模板
/*
int 参数三;
void 参数五(int,void*)//回调函数
{
    /*
    随着滑动条的移动改变参数三,写出相应的反应
    */
}
createTrackbar(参数一,参数二, & 参数三 ,参数四,callback,0);
参数一:滑动条的名字
参数二:滑动条依附的窗口名字,即滑动条要在哪里显示
参数三:滑动条要改变的值
参数四:滑动条参数改变时的最大值
参数五:回调函数的名字

参数五(参数三,0);//回调函数声明
*/
# include 
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;

int value;
double Fps;
int framePos;
Mat frame;
Mat frame1;

void callback (int ,void*)
{
    threshold(frame,frame1,value,255,THRESH_BINARY);
    imshow("Video",frame);
}

int main (void)
{
    char strFps[20];
    VideoCapture cap("视频地址");
    if(!cap.isOpened())
        return -1;
    int totalFrame=vc.get(CV_CAP_PROP_FRAME_COUNT);//获取总帧数
    namedWindow("Video",CV_WINDOW_AUTOSIZE);
    createTrackbar("Frame","Video",&value,totalFrame,callback,0); //第二个参数要和窗口名保持一致   
    Fps=cap.get(CV_CAP_PROP_FPS);//获取视频帧率
    sprintf(strFps,"Fps:%lf",Fps);


    while(1)
    {
        framePos=cap.get(CV_CAP_PROP_POS_FRAMES);//获取视频帧当前位置
        setTrackbarPos("Frame","Video",framePos);//设置滑动条位置
        cap>>frame;
        if(frame.empty())
            break;
        putText(frame,strFps,Point(5,30),CV_FONT_HERSHEY_COMPLEX_SMALL,1,Scalar(0,255,0),1,8);
        imshow("Video",frame);
        if(27==waitKey(1000/Fps))//需要和帧率保持一样
            break;
    }
    cap.release();
    destroyALLWindow();
    return 0;
}

五、opencv图像的运算

# include 
# include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main ()
{
    Mat image1,image2,image3;
    //图像加法(大于255按255算)
    //第一种:
    image3=image1+image2;
    //第二种:
    add(image1,image2,image3);
    //第三种:
    addWeighted(image1,0.5,image2,0.5,0,image3);//0.5是在加法中所占的比例

    //图像减法
    //第一种:
    image3=image1-image2;//小于0按0计算
    //第二种:
    subtract(image1,image2,image3);//小于0按0计算
    //第三种:
    absdiff(image1,image2,image3);//小于0按绝对值计算

    //图像乘除法
    int i;
    image3=image1*i;//大于255按255计算
    image3=image1/i;

    //逻辑与或非
    bitwise_and(image1,image2,image3);//逻辑与,求交集
    bitwise_or(image1,image2,image3);//逻辑或,求并集
    bitwise_not(image1,image3);//逻辑非,求补集
    bitwise_xor(image1,image2,image3);//逻辑异或,交集取反,补集不动

    return 0;
}

六、图像的通道分离

# include "ros/ros.h"
# include 
# include 
# include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main ()
{
    Mat img=imread("1.jpg");
    vector channels;

    split(img,channels);
    Mat blueChannel=channels.at(0);
    Mat greenChannel=channels.at(1);
    Mat redChannel=channels.at(2); 

    imshow("blue",blueChannel);
    imshow("green",greenChannel);
    imshow("red",redChannel);

    return 0;
}

七、图像滤波

# include "ros/ros.h"
# include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main ()
{
    Mat srcImag=imread("/home/zhangpeng/catkin_wsfour/1.jpg");
    Mat dstImag;
    Size size0=Size(3,3);
    if(srcImag.empty())
    { 
	return -1;
    }
    //线性滤波
    boxFilter(srcImag,dstImag,-1,Size(5,5),Point(-1,-1),false);//方框滤波器
    /*
    第一个参数:原图
    第二个参数:目标图像
    第三个参数:输出图像深度,一般使用-1表示输入图像和输出图像深度一致
    第四个参数:内核大小,值越大,滤波效果越好
    第五个参数:锚点,默认值是Point(-1,-1),表示锚点在内核的中心
    第六个参数:true或false
    */
    blur(srcImag,dstImag,size0);//均值滤波
    /*
    第一个参数:原图
    第二个参数:目标图像
    第三个参数:内核大小,值越大,滤波效果越好
    */
    GuassianBlur(srcImag,dstImag,size0);//高斯滤波
    /*
    第一个参数:原图
    第二个参数:目标图像
    第三个参数:内核大小,值越大,滤波效果越好
    */
    //非线性滤波
    medianBlur(srcImag,dstImag,5);//中值滤波
    /*
    第一个参数:原图
    第二个参数:目标图像
    第三个参数:内核大小,值越大,滤波效果越好,必须是奇数
    */
    imshow("src",srcImag);
    imshow("dst",dstImag);
    waitKey(0);
    return 0;
}

八、转化为灰度图的方法:

//第一种方法
Mat img1=imread("1.jpg",0);
//第二种方法
Mat img1=imread("1.jpg");
Mat img2;
cvtColor(img1,img2,CV_BGR2GRAY);

九、图像阈值

//固定阈值
# include "ros/ros.h"
# include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main ()
{
    Mat img1=imread("/home/zhangpeng/catkin_wsfour/two.jpg",0);
    Mat img2;
    if (img1.empty())
    {
        return -1;
    }
    //imshow("huidu",img1);
    threshold(img1,img2,100,255,CV_THRESH_BINARY);
/*
第一个值:原图(必须是灰度图)
第二个值:输出图像
第三个值:阈值
第四个值:第五个参数为CV_THRESH_BINARY、CV_THRESH_BINARY_INV是的最大值,一般为255
第五个值:可以取CV_THRESH_BINARY、CV_THRESH_BINARY_INV、CV_THRESH_TRUNC、CV_THRESH_TOZERO、CV_THRESH_TOZERO_INV
*/
    if (img2.empty())
    {
        return -1;
    }
    imshow("yuantu",img1);
    imshow("mubiao",img2);
    waitKey(0);
    return 0;
}


//自定义阈值
# include "ros/ros.h"
# include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main ()
{
    Mat img1=imread("/home/zhangpeng/catkin_wsfour/two.jpg",0);
    Mat img2;
    if (img1.empty())
    {
        return -1;
    }
                              
adaptiveThreshold(img1,img2,255,CV_ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY,11,5);
/*
第一个值:原图(必须是灰度图)
第二个值:输出图像
第三个值:最大值,一般为255
第四个值:自定义阈值算法,只能取CV_ADAPTIVE_THRESH_GAUSSIAN_C或者CV_ADAPTIVE_THRESH_MEAN_C
第五个值:CV_THRESH_BINARY或者CV_THRESH_BINARY_INV两者其一
第六个值:用来计算阈值的领域大小,只能取3,5,7等奇数
第七个值:减去平均或加权平均后的常数值
*/  
    if (img2.empty())
    {
        return -1;
    }
    imshow("yuantu",img1);
    imshow("mubiao",img2);
    waitKey(0);
    return 0;
}

十、膨胀与腐蚀

# include "ros/ros.h"
# include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main ()
{
    Mat img1=imread("1.jpg",0);
    if (img1.empty())
    {
        return -1;
    }
    Mat img2;
    Mat img;
    img=getStructuringElement(MORPH_RECT,Size(5,5));
    cout<

十一、基于膨胀腐蚀的其他形态学操作

# include "ros/ros.h"
# include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main ()
{
    Mat img1=imread("1.jpg",0);
    if (img1.empty())
    {
        return -1;
    }
    Mat img2;
    Mat img;
    img=getStructuringElement(MORPH_RECT,Size(5,5));
    morphologyEx(img1,img2,MORPH_ERODE,img,Point(-1,-1),1);
    /*一般只写前三个参数
    第一个参数:原图
    第二个参数:目标图像
    第三个参数:形态学处理方式,有:
        膨胀:MORPH_ERODE
        腐蚀:MORPH_DILATE
        开运算:MORPH_OPEN 消除小白点
        闭运算:MORPH_CLOSE 消除小黑点
        顶帽(礼帽):MORPH_TOPHAT
        黑帽:MORPH_BLACKHAT
        形态学梯度:MORPH_GRADIENT 得到轮廓
    第四个参数:形态学处理方式
    第五个参数:锚点位置
    第六个参数:处理次数
    第七个参数:边界模式,一般为默认值
    第八个参数:边界值,一般为默认值
    */
    imshow("pengzhang",img2);
    //imshow("fushi",img2);
    waitKey(0);
    return 0;
}

十二、边缘检测

Canny算子检测:

# include "ros/ros.h"
# include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
    Mat img1=imread("1.jpg");
    if (img1.empty())
    {
        return -1;
    }
    imshow("yuantu",img1);
    Mat img2;
    Canny(img1,img2,30,80);//Canny算子
    /*一般只写前四个
    第一个值:原图
    第二个值:目标图
    第三个值:滞后阈值低阈值//高阈值比低阈值最好介于2:1到3:1之间
    第四个值:滞后阈值高阈值
    第五个值:孔径大小,一般默认为3
    第六个值:计算图像梯度幅值的标识,一般默认为false
    */
    if (img2.empty())
    {
        return -1;
    }
    imshow("mubiao",img2);
    waitKey(0);
    return 0;
}

Sobel算子检测

# include "ros/ros.h"
# include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
    Mat img1=imread("1.jpg");
    if (img1.empty())
    {
        return -1;
    }
    imshow("yuantu",img1);
    Mat img2;
    Mat img3;
    Sobel(img1,img2,CV_16S,3,3);//Sobel算子
    convertScaleAbs(img2,img3);//Sobel算子用了CV_16S,这里调用另一个函数将其转化为正确图像
    /*一般只写前五个
    第一个值:原图
    第二个值:目标图
    第三个值:输出图像的深度,默认为CV_16U
    第四个值:x方向的差分阶数/*对x方向求导,就写为 1 对y方向求导就写为 0 x方向求导即为横向消失,y方向求导即为纵向消失
    第五个值:y方向的差分阶数                   0                1
    第六个值:默认
    第七个值:默认
    第八个值:默认
    第九个值:默认
    */
    if (img2.empty())
    {
        return -1;
    }
    imshow("mubiao",img2);
    waitKey(0);
    return 0;
}

霍夫线检测

# include "ros/ros.h"
# include "opencv2/opencv.hpp"
# include 
# include 

using namespace std;
using namespace cv;

int main()
{
    Mat img1;
    Mat img2=imread("1,jpg");
    Mat img3=img2.clone();
    if (img2.empty())
    {
        return -1;
    }
    imshow("yuantu",img2);
    cvtColor(img2,img2,CV_BGR2GRAY);
    Canny(img2,img1,50,200,3);
    if (img1.empty())
    {
        return -1;
    }
    imshow("Canny",img1);
    vectorlines;
    HoughLines(img1,lines,1,CV_PI/180,150,0,0);
    /*
    第一个值:原图
    第二个值:检测线条的输出矢量
    第三个值:以像素为单位的距离精度,一般为1
    第四个值:以弧度为单位的距离精度,一般为CV_PI/180,CV_PI是圆周率
    第五个值:累加平面的阈值参数,大于这个阈值才会被检测出来,自己写
    第六个值:最低线段长度,小于这一长度则检测不出来,默认为0
    第七个值:允许将同一行点与点连接起来的最小长度,默认为0
    */
    for (size_t i = 0; i < lines.size(); i++)
    {
        float rho=lines[i][0],theta=lines[i][1];
        Point pt1,pt2;
        double a=cos(theta),b=sin(theta);
        double x0=a*rho,y0=b*rho;
        pt1.x=cvRound(x0+1000*(-b));
        pt1.y=cvRound(y0+1000*(a));
        pt2.x=cvRound(x0-1000*(-b));
        pt2.y=cvRound(y0-1000*(a));
        line(img3,pt1,pt2,Scalar(0,0,255),1,CV_AA);
    }
    if (img3.empty())
    {
        return -1;
    }
    imshow("Line",img3);
    waitKey(0);
    return 0;
}

霍夫圆检测

# include "ros/ros.h"
# include "opencv2/opencv.hpp"
# include 
# include 

using namespace std;
using namespace cv;

int main()
{
    Mat src=imread("1.jpg");
    Mat dst=src.clone();
    if (src.empty())
    {
        return -1;
    }
    imshow("src",src);
    cvtColor(src,src,CV_BGR2GRAY);
    GaussianBlur(src,src,Size(5,5),2,2);//高斯滤波
    vectorcircles;
    HoughCircles(src,circles,CV_HOUGH_GRADIENT,1.5,30,100,100,10,200);
    /*
    第一个值:原图
    第二个值:检测圆的输出矢量
    第三个值:使用的检测方法,一般只有一种CV_HOUGH_GRADIENT
    第四个值:是一个比例,可以试试
    第五个值:圆心之间的最小距离,用来分辨两个不同的圆
    第六个值:默认100
    第七个值:默认100
    第八个值:圆半径的最小值
    第九个值:圆半径的最大值
    */
    for (size_t i = 0; i < circles.size(); i++)
    {
        Point center(cvRound(circles[i][0]),cvRound(circles[i][1]));
        int radius=cvRound(circles[i][2]);
        circle(dst,center,3,Scalar(0,0,255),-1,8,0);
        circle(dst,center,radius,Scalar(0,255,0),3,8,0);
    }
    if (dst.empty())
    {
        return -1;
    }
    imshow("dst",dst);
    waitKey(0);
    return 0;
}

十三、绘制直方图

# include "ros/ros.h"
# include "opencv2/opencv.hpp"
# include 
# include 
# include 

using namespace std;
using namespace cv;

int main ()
{
    srand ( time ( NULL ) );
    Mat img=imread("/home/zhangpeng/catkin_wsfour/two.jpg",0);
    if (img.empty())
    {
        return -1;
    }
    imshow("img",img);
    Mat dstHist;
    int dims=1;
    float hranges[]={0,256};
    const float*ranges[]={hranges};
    int bins=256;
    int channels=0;
    
    calcHist(&img,1,&channels,Mat(),dstHist,dims,&bins,ranges);

    int scale=1;
    Mat dstImg(bins*scale,bins*3,CV_8UC3,Scalar(0));
    double minValue=0;
    double maxValue=0;
    minMaxLoc(dstHist,&minValue,&maxValue,0,0);
    int hpt=saturate_cast(0.9*bins);
    int j=0;
    for (size_t i = 0; i < 256; i++)
    {
        float binValue=dstHist.at(i);
        cout<<"i="<(binValue*hpt/maxValue);
        //line(dstImg,Point(i*scale,bins-1),Point(i*scale,bins-realValue),Scalar(0,255,0),1,8);
        rectangle(dstImg,Point(j*scale,bins-1),Point((j+2)*scale-1,bins-realValue),Scalar(rand()%255,rand()%255,rand()%255),-1);
        j=j+3;
    }
    if (dstImg.empty())
    {
        return -1;
    }
    imshow("dstImg",dstImg);
    waitKey(0);
    return 0;
}

十四、图像均衡化

让不清晰图片更加清晰

# include "opencv2/opencv.hpp"
# include "ros/ros.h"

using namespace std;
using namespace cv;

int main ()
{
    Mat img1=imread("1.jpg",0);//只能处理灰度图
    if (img1.empty())
    {
        return -1;
    }
    imshow("img1",img1);

    Mat img2;
    equalizeHist(img1,img2);//均衡化处理
    if (img2.empty())
    {
        return -1;
    }
    imshow("img2",img2);
    waitKey(0);
    
    return 0;
}

十五、图像匹配

单模板匹配

# include "opencv2/opencv.hpp"
# include "ros/ros.h"

using namespace std;
using namespace cv;

int main ()
{
    Mat temp=imread("/home/zhangpeng/catkin_wsfour/testone.jpg");//模板图像
    Mat src=imread("/home/zhangpeng/catkin_wsfour/two.jpg");//待搜索图像
    if (temp.empty())
    {
        return -1;
    }
    imshow("temp",temp);
    if (src.empty())
    {
        return -1;
    }
    imshow("src",src);
 
    Mat dst=src.clone();//模板图像备份
 
    int width=src.cols-temp.cols+1;
    int height=src.rows-temp.rows+1;
 
    Mat result(height,width,CV_32FC1);//创建结果映射图像

    matchTemplate(src,temp,result,CV_TM_CCOEFF_NORMED);//寻找最佳匹配

    if (result.empty())
    {
        return -1;
    }
    imshow("result",result);

    normalize(result,result,0,1,NORM_MINMAX,-1);//归一化到0-1

    double minValue,maxValue;
    Point minLoc,MaxLoc;
    minMaxLoc(result,&minValue,&maxValue,&minLoc,&MaxLoc);

    rectangle(dst,MaxLoc,Point(MaxLoc.x+temp.cols,MaxLoc.y+temp.rows),Scalar(0,255,0),2,8);

    if (dst.empty())
    {
        return -1;
    }
    imshow("dst",dst);

    waitKey(0);
    return 0;
}

视频匹配

​

# include "opencv2/opencv.hpp"
# include "ros/ros.h"

using namespace std;
using namespace cv;

int main ()
{
    Mat frame;
    Mat templateImg=imread("/home/zhangpeng/catkin_wsfour/me.jpg");
    Mat resultImg;
    VideoCapture cap(0);
    if (!cap.isOpened())
    {
        return -1;
    }
    int resultImg_cols;
    int resultImg_rows;

    while (1)
    {
        cap>>frame;
        if (frame.empty())
        {
            return -1;
        }
        Mat showImg=frame.clone();
        //imwrite("me.jpg",frame);
        resultImg_cols=frame.cols-templateImg.cols+1;
        resultImg_rows=frame.rows-templateImg.rows+1;
        resultImg.create(resultImg_cols,resultImg_rows,CV_32FC1);
        matchTemplate(frame,templateImg,resultImg,CV_TM_CCOEFF_NORMED);
        normalize(resultImg,resultImg,0,1,NORM_MINMAX,-1);

        double minValue,maxValue;
        Point minLoc,maxLoc;
        Point matchLoc;

        minMaxLoc(resultImg,&minValue,&maxValue,&minLoc,&maxLoc);
        if (maxValue>=0.7)
        {
            rectangle(showImg,maxLoc,Point(maxLoc.x+templateImg.cols,maxLoc.y+templateImg.rows),Scalar(0,255,0),2); 
        }
        if (frame.empty())
        {
            return -1;
        }
        imshow("frame",frame);
        if (showImg.empty())
        {
            return -1;
        }
        imshow("result",showImg);
        if (27==waitKey(10))
        {
            break;
        }
        
    }
    return 0;
}

[点击并拖拽以移动]
​

十六、轮廓查找与绘制

# include "opencv2/opencv.hpp"
# include "ros/ros.h"

using namespace std;
using namespace cv;

int main ()
{
    Mat srcImg=imread("1.jpg");
    Mat tempImg=srcImg.clone();
    Mat draw(srcImg.rows,srcImg.cols,CV_8UC3);
    cvtColor(srcImg,srcImg,CV_BGR2GRAY);//转化为灰度图
    threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY);
    if (srcImg.empty())
    {
        return -1;
    }
    imshow("srcImg",srcImg);

    vector>contours;
    vectorhierarchy;

    findContours(srcImg,contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);//查找轮廓
    /*
    第一个值:要处理的图像,一般为二值图
    第二个值:所有检测出的轮廓
    第三个值:输出向量
    第四个值:轮廓检索模式
        CV_RETR_EXTERNAL=0 只检测最外层轮廓
        CV_RETR_LIST=1 提取所有轮廓放在list中
        CV_RETR_CCOMP=2 提取所有轮廓并组织为双层结构
        CV_RETR_TREE=3 提取所有轮廓并建立网状结构
    第五个值:轮廓的近似方法
        CV_CHAIN_APPROX_SIMPLE 只保存端点
        CV_CHAIN_APPROX_NONE 保存所有点
        CV_CHAIN_APPROX_TC89_L1
        CV_CHAIN_APPROX_TC89_KCOS
    第七个值:默认
    */
    if (srcImg.empty())
    {
        return -1;
    }
    imshow("cont",srcImg);
    drawContours(draw,contours,-1,Scalar(0,255,0),2,8);//绘制轮廓
    /*
    第一个值:目标图像,轮廓所在位置
    第二个值:所有的输入轮廓
    第三个值:轮廓的索引,若为-1则表示所有轮廓
    第四个值:颜色
    第五个值:轮廓线的粗细
    第六个值:轮廓线的类型
    第七个值:默认
    第八个值:默认
    第九个值:默认
    */
    if (draw.empty())
    {
        return -1;
    }
    imshow("contours",draw);
    waitKey(0);
    return 0;
}
    
   

十七、访问轮廓的每一个点

# include "opencv2/opencv.hpp"
# include "ros/ros.h"

using namespace std;
using namespace cv;

int main ()
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/two.jpg");
    if (srcImg.empty())
    {
        return -1;
    }
    imshow("src",srcImg);
    Mat tempImg=srcImg.clone();
    cvtColor(srcImg,srcImg,CV_BGR2GRAY);
    threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY_INV);

    vector>contours;
    vectorhierarcy;

    findContours(srcImg,contours,hierarcy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE);//找轮廓

    for (size_t i = 0; i < contours.size(); i++)//访问每一个点
    {
        for (size_t j = 0; j < contours[i].size(); j+=50)
        {
            circle(tempImg,Point(contours[i][j].x,contours[i][j].y),3,Scalar(0,255,0),2,8);
            line(tempImg,Point(10,10),Point(contours[i][j].x,contours[i][j].y),Scalar(0,0,255),1,8);
            waitKey(100);
            if (tempImg.empty())
            {
                return -1;
            }
            imshow("contours",tempImg);
        }
        
        drawContours(tempImg,contours,i,Scalar(0,255,0),2,8);//绘制轮廓

    }

    // if (tempImg.empty())
    // {
    //     return -1;
    // }
    // imshow("contours",tempImg);

    waitKey(0);
    
    return 0;
}
    
   

十八、轮廓之“点集凸包”

# include "ros/ros.h"
# include "opencv2/opencv.hpp"
# include 

using namespace std;
using namespace cv;

int main (void)
{
    Mat img(500,500,CV_8UC3,Scalar::all(0));
    RNG rng;//自定义随机数对象
    while (1)
    {
        char key;
        int count=(unsigned int)rng%100;//定义点的个数
        vectorpoints;//定义点集
        for (size_t i = 0; i < count; i++)
        {
            Point pt;
            pt.x=rng.uniform(img.cols/4,img.cols*3/4);//设定点的x的范围
            pt.y=rng.uniform(img.rows/4,img.rows*3/4);//设定点的y的范围
            points.push_back(pt);
        }
        //检测凸包
        vectorhull;//用来储存凸包的边数
        convexHull(Mat(points),hull,true);

        img=Scalar::all(0);//将图片清0

        //准备参数
        int hullcount=(int)hull.size();//凸包的边数
        Point point0=points[hull[hullcount-1]];//连接凸包边的坐标点

        //绘制凸包
        for (size_t i = 0; i < hullcount; i++)
        {
            Point point=points[hull[i]];
            circle(img,point,8,Scalar(0,255,0),2,8);
            line(img,point0,point,Scalar(255,255,255),2,CV_AA);
            point0=point;        
        }

        //显示效果
        if (img.empty())
        {
	    cout<<"aaa"<

十九、轮廓之“图片凸包”

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;

int main ()
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/two.jpg");
    if (srcImg.empty())
    {
        return -1;
    }
    imshow("src1",srcImg);
    Mat dstImg(srcImg.rows,srcImg.cols,CV_8UC3,Scalar::all(0));
    cvtColor(srcImg,srcImg,CV_BGR2GRAY);//转化为灰度图
    if (srcImg.empty())
    {
        return -1;
    }
    imshow("src2",srcImg);
    threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY_INV);//二值化
    if (srcImg.empty())
    {
        return -1;
    }
    imshow("src3",srcImg);
 
    vector>contours;//存放轮廓的个数
    vectorhierarcy;

    findContours(srcImg,contours,hierarcy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓
    vector>hull(contours.size());
    for (size_t i = 0; i < contours.size(); i++)//检测凸包
    {
        convexHull(Mat(contours[i]),hull[i],true);
    }
    for (size_t i = 0; i < contours.size(); i++)
    {
        drawContours(dstImg,contours,i,Scalar(255,255,255));//绘制轮廓
        drawContours(dstImg,hull,i,Scalar(rand()%255,rand()%255,rand()%255),2,8);//绘制凸包
    }
    if (dstImg.empty())
    {
        return -1;
    }
    imshow("dst",dstImg);
    waitKey(0);
    
    return 0;
}

二十、轮廓之外接矩形的查找与绘制

# include "ros/ros.h"
# include "opencv2/opencv.hpp"
# include 


using namespace cv;
using namespace std;

int main (void)
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/two.jpg");
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("src",srcImg);
    Mat dstImg=srcImg.clone();
    cvtColor(srcImg,srcImg,CV_BGR2GRAY);
    threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY);
    vector>contours;
    vectorhierarcy;
    findContours(srcImg,contours,hierarcy,CV_RETR_EXTERNAL,CHAIN_APPROX_NONE);//查找轮廓
    vectorboundRect(contours.size());
    drawContours(dstImg,contours,-1,Scalar(0,0,255),2,8);//绘制轮廓
    int x0=0,y0=0,w0=0,h0=0;
    for (size_t i = 0; i < contours.size(); i++)
    {
        boundRect[i]=boundingRect((Mat)contours[i]);//查找每个轮廓的外接矩形
        drawContours(dstImg,contours,i,Scalar(0,0,255),2,8);//绘制轮廓
        x0=boundRect[i].x;
        y0=boundRect[i].y;
        w0=boundRect[i].width;
        h0=boundRect[i].height;
        rectangle(dstImg,Point(x0,y0),Point(x0+w0,y0+h0),Scalar(0,255,0),2,8);
    }
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("srcImg",dstImg);
    waitKey(0);
    return 0;
}

二十一、最小外接矩形

# include "ros/ros.h"
# include "opencv2/opencv.hpp"
# include 


using namespace cv;
using namespace std;

int main (void)
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/2.jpg");
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("srcImg",srcImg);
    Mat dstImg=srcImg.clone();

    cvtColor(srcImg,srcImg,CV_BGR2GRAY);
    threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY_INV);
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("srcImg1",srcImg);

    vector>contours;
    vectorhierarcy;

    findContours(srcImg,contours,hierarcy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);

    vectorboundRect(contours.size());//定义外接矩形集合
    vectorbox(contours.size());//定义最小外接矩形集合
    Point2f rect[4];

    for (size_t i = 0; i < contours.size(); i++)
    {
        box[i]=minAreaRect(Mat(contours[i]));//计算最小外接矩形
        boundRect[i]=boundingRect(Mat(contours[i]));
        box[i].points(rect);//八最小外接矩形的四个端点赋值给rect数组
        for (size_t j = 0; j < 4; j++)
        {
            line(dstImg,rect[j],rect[(j+1)%4],Scalar(0,0,255),2,8);//绘制最小矩形的四条边
        }
    }
    if(dstImg.empty())
    {
        return -1;
    }
    imshow("dst",dstImg);
    waitKey(0);
    return 0;
}

二十二、点与轮廓的位置关系

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;

int main (void)
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/1.jpg");
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("srcImg1",srcImg);

    Mat dstImg=srcImg.clone();
    cvtColor(srcImg,srcImg,CV_BGR2GRAY);
    threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY);
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("srcImg2",srcImg);

    vector>contours;
    vectorhierarcy;

    findContours(srcImg,contours,hierarcy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓
    for (size_t i = 0; i < contours.size(); i++)//遍历轮廓的每一个点
    {
        for (size_t j = 0; j < contours[i].size(); j++)
        {
            cout<<"("<

二十三、目标查找之轮廓查找

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 
# include 

using namespace std;
using namespace cv;

int main (void)
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/5.jpg");
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("srcImg",srcImg);
    cvtColor(srcImg,srcImg,CV_BGR2GRAY);
    threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY);
    imwrite("5.jpg",srcImg);
    vector>contours1;
    vectorhierarcy1;
    findContours(srcImg,contours1,hierarcy1,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓
 
    Mat dstImg=imread("/home/zhangpeng/catkin_wsfour/3.jpg");
    if(dstImg.empty())
    {
        return -1;
    }
    imshow("dstImg",dstImg);
    Mat dstImg1=dstImg.clone();
    cvtColor(dstImg,dstImg,CV_BGR2GRAY);
    threshold(dstImg,dstImg,100,255,CV_THRESH_BINARY);
    vector>contours2;
    vectorhierarcy2;
    findContours(dstImg,contours2,hierarcy2,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓

    while (1)
    {
        for (size_t i = 0; i < contours2.size(); i++)
        {
            double matchRate=matchShapes(contours1[0],contours2[i],CV_CONTOURS_MATCH_I1,0.0);
            /*
            第一个参数:所需比较轮廓
            第二个参数:所需比较轮廓
            第三个参数:轮廓比较方法
            第四个参数:不用管
            */
            //cout<<"index="<
            if(matchRate<=0.1)
            {
                drawContours(dstImg1,contours2,i,Scalar(0,255,0),2,8);
            }
            imshow("dst",dstImg);
        }
        
    }
    return 0;
}

二十四、颜色目标检测

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;
//绿色的阈值
int h_min=35;
int s_min=110;
int v_min=106;
//绿色的阈值
int h_max=77;
int s_max=255;
int v_max=255;

int main (void)
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/1.jpg");
    if(srcImg.empty())
    {
        return -1;
    }
    imshow("src",srcImg);
    Mat dstImg=srcImg.clone();
    Mat hsv_img;
    cvtColor(srcImg,hsv_img,CV_BGR2HSV);//BGR转化为HSV
    Scalar hsv_min(h_min,s_min,v_min);
    Scalar hsv_max(h_max,s_max,v_max);
    Mat hsv_green=Mat::zeros(srcImg.size(),CV_8U);
    inRange(hsv_img,hsv_min,hsv_max,hsv_green);//颜色区间筛选
    /*
    第一个参数:原图
    第二个参数:颜色低阈值
    第三个参数:颜色高阈值
    第四个参数:输出目标图像,是二值图类型,目标是白色,其余是黑色
    */
    if(hsv_green.empty())
    {
        return -1;
    }
    imshow("hsv_green",hsv_green);
    
    vector>contours;
    vectorhierarcy;
    findContours(hsv_green,contours,hierarcy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓

    vectorboundRect(contours.size());
    for (size_t i = 0; i < contours.size(); i++)
    {
        boundRect[i]=boundingRect(Mat(contours[i]));
        rectangle(dstImg,boundRect[i].tl(),boundRect[i].br(),Scalar(0,255,255),2,8);
        Point org=boundRect[i].tl();
        putText(dstImg,"green",org,CV_FONT_HERSHEY_SIMPLEX,1.2f,Scalar(255,0,0),2);
    }
    if(dstImg.empty())
    {
        return -1;
    }
    imshow("result",dstImg);
    
 
    waitKey(0);

    return 0;
}

二十五、颜色识别之摄像头三色识别(自己做的)

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;
//绿色的阈值
int h_min=60;
int s_min=100;
int v_min=100;
//绿色的阈值
int h_max=75;
int s_max=255;
int v_max=255;

//红色的阈值
int h_rmin=0;
int s_rmin=100;
int v_rmin=100;
//红色的阈值
int h_rmax=10;
int s_rmax=255;
int v_rmax=255;

//蓝色的阈值
int h_bmin=90;
int s_bmin=100;
int v_bmin=100;
//蓝色的阈值
int h_bmax=120;
int s_bmax=255;
int v_bmax=255;


int main (void)
{
    VideoCapture cap(0);
    if(!cap.isOpened())
    {
        return -1;
    }
    while (waitKey(1)!=27)
    {
        Mat srcImg;
        cap>>srcImg;
        
        Mat dstImg=srcImg.clone();


        Mat hsv_img;
        cvtColor(srcImg,hsv_img,CV_BGR2HSV);//BGR转化为HSV


	//green
        Scalar hsv_min(h_min,s_min,v_min);
        Scalar hsv_max(h_max,s_max,v_max);
        Mat hsv_green=Mat::zeros(srcImg.size(),CV_8U);
        inRange(hsv_img,hsv_min,hsv_max,hsv_green);//颜色区间筛选
     
        vector>contours;
        vectorhierarcy;
        findContours(hsv_green,contours,hierarcy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓

        vectorboundRect(contours.size());
        for (size_t i = 0; i < contours.size(); i++)
        {
            boundRect[i]=boundingRect(Mat(contours[i]));
            if(boundRect[i].width>150&&boundRect[i].height>150)
            {
                rectangle(dstImg,boundRect[i].tl(),boundRect[i].br(),Scalar(0,255,255),2,8);
                Point org=boundRect[i].tl();
                putText(dstImg,"green",org,CV_FONT_HERSHEY_SIMPLEX,1.2f,Scalar(255,0,0),2);
            }
        }

	
	//red
        Scalar hsv_rmin(h_rmin,s_rmin,v_rmin);
        Scalar hsv_rmax(h_rmax,s_rmax,v_rmax);
        Mat hsv_red=Mat::zeros(srcImg.size(),CV_8U);
        inRange(hsv_img,hsv_rmin,hsv_rmax,hsv_red);//颜色区间筛选
     
        vector>contours1;
        vectorhierarcy1;
        findContours(hsv_red,contours1,hierarcy1,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓

        vectorboundRect1(contours1.size());
        for (size_t j = 0; j < contours1.size(); j++)
        {
            boundRect1[j]=boundingRect(Mat(contours1[j]));
            if(boundRect1[j].width>150&&boundRect1[j].height>150)
            {
                rectangle(dstImg,boundRect1[j].tl(),boundRect1[j].br(),Scalar(0,0,255),2,8);
                Point org=boundRect[j].tl();
                putText(dstImg,"red",org,CV_FONT_HERSHEY_SIMPLEX,1.2f,Scalar(255,0,0),2);
            }
        }


	//blue
	Scalar hsv_bmin(h_bmin,s_bmin,v_bmin);
        Scalar hsv_bmax(h_bmax,s_bmax,v_bmax);
        Mat hsv_blue=Mat::zeros(srcImg.size(),CV_8U);
        inRange(hsv_img,hsv_bmin,hsv_bmax,hsv_blue);//颜色区间筛选
     
        vector>contours2;
        vectorhierarcy2;
        findContours(hsv_blue,contours2,hierarcy2,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);//找轮廓

        vectorboundRect2(contours2.size());
        for (size_t a = 0; a < contours2.size(); a++)
        {
            boundRect2[a]=boundingRect(Mat(contours2[a]));
            if(boundRect2[a].width>150&&boundRect2[a].height>150)
            {
                rectangle(dstImg,boundRect2[a].tl(),boundRect2[a].br(),Scalar(0,255,255),2,8);
                Point org=boundRect2[a].tl();
                putText(dstImg,"blue",org,CV_FONT_HERSHEY_SIMPLEX,1.2f,Scalar(255,0,0),2);
            }
        }


        if(dstImg.empty())
        {
            return -1;
        }
        imshow("result",dstImg);
    }
 
    waitKey(0);

    return 0;
}

二十六、分水岭算法

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;

int main (void)
{
    Mat srcImg=imread("/home/zhangpeng/catkin_wsfour/two.jpg");
    imshow("srcImg",srcImg);
    //Mat dstImg=srcImg.clone();
    Mat imgMask(srcImg.size(),CV_8U,Scalar(0));//创建8位单通道
 
    //标识背景
    rectangle(imgMask,Point(1,1),Point(srcImg.cols-2,srcImg.rows-2),Scalar(255),1);
    //标识待测物体
    rectangle(imgMask,Point(108,274),Point(154,340),Scalar(255),1);
 
    imshow("mask",imgMask);

    imgMask.convertTo(imgMask,CV_32S);//用convertTo()函数创建32位单通道
 
    watershed(srcImg,imgMask);//分水岭算法
    /*
    第一个参数:输入图像,必须是8位三通道彩色图像
    第二个参数:函数调用厚的结果,必须是32位单通道,要和原图大小一致
    */
    
    Mat mark1;

    imgMask.convertTo(mark1,CV_8U);//创建8位单通道

    imshow("marker",mark1);
    waitKey(0);
    return 0;
}

二十七、角点检测

(1)Harris角点检测

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;

int main (void)
{
    Mat img=imread("/home/zhangpeng/catkin_wstest/two.jpg");
    if(img.empty())
    {
	return -1;
    }
    imshow("src",img);
    Mat result=img.clone();
    Mat gray;
    cvtColor(img,gray,CV_BGR2GRAY);//灰度图

    Mat dst;
    Mat corner_img;
    cornerHarris(gray,corner_img,2,3,0.04);//角点检测
    /*
    第一个参数:输入原图,须是8位单通道
    第二个参数:检测结果
    第三个参数:领域大小
    第四个参数:孔径大小
    第五个参数:取值0.04~0.06之间
    */
    if(corner_img.empty())
    {
	return -1;
    }
    imshow("corner",corner_img);
    threshold(corner_img,dst,0.015,255,CV_THRESH_BINARY);//二值图
    if(dst.empty())
    {
	return -1;
    }
    imshow("dst",dst);

    int rowNumber=gray.rows;
    int colNumber=gray.cols;
    
    for (size_t i = 0; i < rowNumber; i++)
    {
        for (size_t j = 0; j < colNumber; j++)
        {
            if(dst.at(i,j)==255)
            {
                circle(result,Point(j,i),5,Scalar(0,255,0),2,8);
            }
        }
        
    }
    if(result.empty())
    {
	return -1;
    }
    imshow("result",result);
    waitKey(0);
    return 0;
}

(2)goodFeaturesToTrack角点检测

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;

int main (void)
{
    Mat img=imread("/home/zhangpeng/catkin_wstest/two.jpg");
    if(img.empty())
    {
	return -1;
    }
    imshow("src",img);
    Mat result=img.clone();
    Mat gray;
    cvtColor(img,gray,CV_BGR2GRAY);//灰度图

    vectorcorners;
    goodFeaturesToTrack(gray,corners,100,0.01,10,Mat(),3,false,0.04);
    /*
    第一个参数:输入图像,8位32位浮点型或者单通道图像
    第二个参数:角点的输出向量
    第三个参数:角点的最大数量
    第四个参数:角点检测可以接受的最小特征值,一般取值0.1或者0.01
    第五个参数:角点之间的最小距离,用于过滤距离太近的点
    第六个参数:掩码
    第七个参数:默认为3
    第八个参数:默认为false,指示不用Harris检测
    第九个参数:默认为0.04
    */
    cout<<"Number:"<

二十八、运动物体目标检测

# include "opencv2/opencv.hpp"
# include "ros/ros.h"
# include 

using namespace std;
using namespace cv;

int main (void)
{
    VideoCapture cap(0);
    if(!cap.isOpened())
    {
        return -1;
    }
    Mat img1=imread("/home/zhangpeng/catkin_wstest/me.jpg");
    while (waitKey(1)!=27)
    {
        //Mat img1=imread("/home/zhangpeng/catkin_wstest/me.jpg");
        Mat img2;
        cap>>img2;
        // imshow("img1",img1);
        // imshow("img2",img2);

        Mat gray1,gray2;//转化为灰度图
        cvtColor(img1,gray1,CV_BGR2GRAY);
        cvtColor(img2,gray2,CV_BGR2GRAY);

        Mat diff;//图像做减法
        absdiff(gray1,gray2,diff);
        //imshow("absdiff",diff);

        threshold(diff,diff,45,255,CV_THRESH_BINARY);//转化为二值图
        //imshow("threshold",diff);

        Mat element1=getStructuringElement(MORPH_RECT,Size(5,5));
        Mat element2=getStructuringElement(MORPH_RECT,Size(15,15));

        erode(diff,diff,element1);//腐蚀
        //imshow("erode",diff);

        dilate(diff,diff,element2);//膨胀
        //imshow("dilate",element2);

        vector< vector >contours;
        vectorhierarcy;
        findContours(diff,contours,hierarcy,CV_RETR_EXTERNAL,CHAIN_APPROX_NONE);//找轮廓

        vectorboundRect(contours.size());
        //drawContours(img2,contours,-1,Scalar(0,0,255),1,8);//绘制轮廓
        int x0=0,y0=0,w0=0,h0=0;
        for (size_t i = 0; i < contours.size(); i++)
        {
            boundRect[i]=boundingRect((Mat)contours[i]);
            x0=boundRect[i].x;
            y0=boundRect[i].y;
            w0=boundRect[i].width;
            h0=boundRect[i].height;
 	    if(w0>50&&h0>50)
            rectangle(img2,Point(x0,y0),Point(x0+w0,y0+h0),Scalar(0,255,0),2,8);//矩形
        }
        imshow("result",img2);
	img1=img2.clone();
	waitKey(30);
    }    
    waitKey(0);
    return 0;
}

你可能感兴趣的:(OpenCV,c++,opencv,计算机视觉,c++)