OpenCV中提供了很多关于图像轮廓处理的函数,这里我用FindContours函数来提取轮廓,并用DrawContours函数将提取的轮廓画出来。函数FindContours的第一个参数就是我们要进行提取轮廓的目标图像,这里要注意,这个图像必须是一个二值图。
代码:
//find
Mat middle = cvarrToMat(SrcImage);
Mat resultImage;
Mat CannyImg;Canny(DstImg, CannyImg, 50, 200, 3);
findContours(DstImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);vector>::iterator itc = contours.begin();
while (itc != contours.end())
{
if (itc->size()<500) //删除连通域面积小于500的轮廓连通域
{
itc = contours.erase(itc);
}
else
{
++itc;
}
}
//draw
Mat result(middle.size(), CV_8U, Scalar(255,255,255));
drawContours(result, contours, -1, Scalar(0,0,0), 2);
效果图
直线检测
霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体。该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。霍夫变换于1962年由Paul Hough 首次提出[53],后于1972年由Richard Duda和Peter Hart推广使用[54],经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆.
经过几天的学习,发现各位大牛的理解方式之前都是有一些区别的,但是核心的思想没有变化,因此记录一下自己对霍夫变换直线检测的认识。
一、原理介绍:
1、对于直角坐标系中的任意一点A(x0,y0),经过点A的直线满足Y0=k*X0+b.(k是斜率,b是截距)
2、那么在X-Y平面过点A(x0,y0)的直线簇可以用Y0=k*X0+b表示,但对于垂直于X轴的直线斜率是无穷大的则无法表示。因此将直角坐标系转换到极坐标系就能解决该特殊情况。
3、在极坐标系中表示直线的方程为ρ=xCosθ+ySinθ(ρ为原点到直线的距离),如图所示:
4、如上图,假定在一个8*8的平面像素中有一条直线,并且从左上角(1,8)像素点开始分别计算θ为0°、45°、90°、135°、180°时的ρ,图中可以看出ρ分别为1、(9√2)/2、8、(7√2)/2、-1,并给这5个值分别记一票,同理计算像素点(3,6)点θ为0°、45°、90°、135°、180°时的ρ,再给计算出来的5个ρ值分别记一票,此时就会发现ρ =(9√2)/2的这个值已经记了两票了,以此类推,遍历完整个8*8的像素空间的时候ρ =(9√2)/2就记了5票, 别的ρ值的票数均小于5票,所以得到该直线在这个8*8的像素坐标中的极坐标方程为(9√2)/2=x*Cos45°+y*Sin45°,到此该直线方程就求出来了。(PS:但实际中θ的取值不会跨度这么大,一般是PI/180)。
代码
Mat image;
cvtColor(result,image, CV_GRAY2BGR);
Mat I;
cvtColor(image,I, CV_BGR2GRAY);
Mat contours1;
Canny(I, contours1, 125, 350);
threshold(contours1, contours1, 128, 255, THRESH_BINARY);
vector<lines;
// 检测直线
HoughLinesP(contours1, lines, 1, CV_PI / 180, 145, 300, 2000);
printf("%d\n", lines.size());
drawDetectLines(image,lines, Scalar(0, 255, 0));
namedWindow("result", 2);
imshow("result", image);
sprintf(image_name, "%d HoughLinesP %s", n, ".jpg");//保存的图片名
imageAddress = path + image_name;
imwrite(imageAddress.c_str(),image); //保存一帧图片
效果图