今天主要是研究另一个比较综合的例子。上一个例子只是简单地检测两个平行直线的线段长度和平行线之间的距离,主要应用了直线细化、霍夫变换等主要手段,那么这一次,我们来对三角形进行处理,对于初学者来说,这样一个三角形图片是经典的:
那么问题来了:
1. 求该三角形的周长
2. 求该三角形的面积
实际上这两个问题就是一个问题:三角形的位置信息?如果我们能得到三角形的三个顶点坐标,那么实际上我们就可以掌握这个三角形所有的信息。于是,我们将这个问题演化成这样一个问题:
求三角形三个顶点的坐标
我们不妨来整理一下思路:
1.该图像噪声比较明显,而且属于椒盐噪声,比较适合用中值滤波得到交清晰的图像;
2.进行边缘检测,对于相对来说比较复杂的图像,我们考虑用经典实用的canny算法进行边缘检测;
3.如果边缘存在厚度,我们要进行边缘细化,这张图边缘黑白分界明显,目测没有必要细化;
4.霍夫变换得到三条直线信息。想要得到线段范围信息,只能采用PPHT方法。
如果顺利的话,四步就能够得到我们想要的结果。那我们看看这样做的效果如何把:
Step1:滤波(在此之前转为灰度图像,此处略)
cvSmooth(gray, middle, CV_MEDIAN, 5, 5);
--------->
Step2:边缘检测
cvCanny(middle, canny, 80, 160);
可以看出,不需要边缘细化
Step3:霍夫变换
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* lines;
lines = cvHoughLines2(canny, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 100, 100, 2000);
int n = 0;
for (int i = 0; i < lines->total; ++i)
{
CvPoint* point = (CvPoint*)cvGetSeqElem(lines, i);
cvCircle(result, point[0], 3, CV_RGB(0, 255, 0));
cvCircle(result, point[1], 3, CV_RGB(0, 255, 0));
cvLine(result, point[0], point[1], CV_RGB(0, 255, 0));
n++;
}
我们可以看到,整体的检测效果还是不错的,但是三角形的顶点检测不一,也就是说三个边长并没有完全检测出来,有漏检测的问题。这个实际上是调参数很难弥补的问题,三条边长检测总会存在误差,所以我们要想办法来解决这个问题。
我们发现,虽然顶点没有检测得很好,但是直线方向检测的非常准确,如果我们能作出这三条直线,求出三条直线的交点,我们就可以完美地得到三角形的顶点,如图:
程序如下:
//这是找两条直线的交点的函数
CvPoint FindPoint(double k1, double b1, int judge1, double k2, double b2, int judge2)
{
CvPoint point;
if (judge1 == 0 && judge2 == 1)
{//第一条直线斜率不存在
point.x = k1;
point.y = k2 * point.x + b2;
}
else if (judge1 == 1 && judge2 == 0)
{
point.x = k2;
point.y = k1 * point.x + b1;
}
else if (judge1 == 0 && judge2 == 0)
{
point.x = 0;
point.y = 0;
}
else
{
point.x = (int)((b2 - b1) / (k1 - k2));
point.y = (int)(k1 * point.x + b1);
}
return point;
}
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* lines;
lines = cvHoughLines2(canny, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 100, 100, 2000);
int n = 0;
double k[3];//保存斜率值
double b[3];//保存截距值
double judge[3];//保存是否斜率不存在的判断值
for (int i = 0; i < lines->total; ++i)
{
CvPoint* point = (CvPoint*)cvGetSeqElem(lines, i);
if (point[0].x == point[1].x)//斜率不存在
{
k[i] = point[0].x;
b[i] = point[0].x;//保存x的值,便于函数计算
judge[i] = 0;//斜率不存在
}
else
{
judge[i] = 1;//斜率存在
//计算斜率
double k0 = (double)(point[0].y - point[1].y) / (double)(point[0].x - point[1].x);
//计算截距
double b0 = (double)(point[0].x * point[1].y - point[1].x * point[0].y) / (double)(point[0].x - point[1].x);
k[i] = k0;
b[i] = b0;
}
n++;
}
std::cout << n << endl;
//找三角形的三个顶点位置
CvPoint last1, last2, last3;
last1 = FindPoint(k[0], b[0], judge[0], k[1], b[1], judge[1]);
last2 = FindPoint(k[0], b[0], judge[0], k[2], b[2], judge[2]);
last3 = FindPoint(k[2], b[2], judge[2], k[1], b[1], judge[1]);
cvCircle(result, last1, 3, CV_RGB(255, 0, 0));
cvCircle(result, last2, 3, CV_RGB(255, 0, 0));
cvCircle(result, last3, 3, CV_RGB(255, 0, 0));
cvLine(result, last1, last2, CV_RGB(0, 255, 0));
cvLine(result, last1, last3, CV_RGB(0, 255, 0));
cvLine(result, last3, last2, CV_RGB(0, 255, 0));
得到检测结果如下:
是不是很不错呢。
得到了三个顶点信息后,那么周长、面积什么都是小意思了。
<!--EndFragment-->
相关推荐
OpenCV-MinGW-Build-OpenCV-4.5.0-with-contrib
赠送jar包:opencv-4.5.1-1.5.5.jar; 赠送原API文档:opencv-4.5.1-1.5.5-javadoc.jar; 赠送源代码:opencv-4.5.1-1.5.5-sources.jar; 赠送Maven依赖信息文件:opencv-4.5.1-1.5.5.pom; 包含翻译后的API文档:...
赠送jar包:opencv-4.5.5-1.5.7.jar; 赠送原API文档:opencv-4.5.5-1.5.7-javadoc.jar; 赠送源代码:opencv-4.5.5-1.5.7-sources.jar; 赠送Maven依赖信息文件:opencv-4.5.5-1.5.7.pom; 包含翻译后的API文档:...
赠送jar包:opencv-4.5.5-1.5.7.jar; 赠送原API文档:opencv-4.5.5-1.5.7-javadoc.jar; 赠送源代码:opencv-4.5.5-1.5.7-sources.jar; 赠送Maven依赖信息文件:opencv-4.5.5-1.5.7.pom; 包含翻译后的API文档:...
赠送jar包:opencv-4.5.1-1.5.5.jar; 赠送原API文档:opencv-4.5.1-1.5.5-javadoc.jar; 赠送源代码:opencv-4.5.1-1.5.5-sources.jar; 赠送Maven依赖信息文件:opencv-4.5.1-1.5.5.pom; 包含翻译后的API文档:...
opencv-3.4.4-android-sdk/sdk/build.gradle opencv-3.4.4-android-sdk/sdk/etc opencv-3.4.4-android-sdk/sdk/java
opencv-4.6.0-android-sdk.zip
opencv-3.4.13-android-sdk .zip压缩包
已编译好的opencv资源
1.android 版的opencv-4.5.5 sdk; 2.含有opencv-contrib-4.5.5 扩展模块; 3.可以在android studio 中加载,通过java 层调用,也可以添加so库+头文件的方式在jni 层调用; 4.适用于arm64-v8a架构,即64bit cpu。
opencv-4.5.4-android-sdk .zip
opencv-4.5.5-vc14_vc15最新版本
opencv_contrib-3.4.1.zip作为opencv-3.4.1的扩展包,,在cmake编译opencv时将解压后modules对应路径填入
opencv-contrib-python-3.4.1.15.whl 包含支持SIFT!!!下载文中链接, pip install opencv-contrib-python-3.4.1.15。找了一上午, 终于在这里发现:...
OpenCV-Python-Toturial-中文版.pdf
opencv-python 3.4.1.15 opencv-contrib-python 3.4.1.15 win64版,opencv-python 3.4.1.15 opencv-contrib-python 3.4.1.15,支持版本:python3.4,3.5,3.6
opencv 安装包 opencv-4.1.2-vc14_vc15 opencv 安装包 opencv-4.1.2-vc14_vc15 opencv 安装包 opencv-4.1.2-vc14_vc15 opencv 安装包 opencv-4.1.2-vc14_vc15 opencv 安装包 opencv-4.1.2-vc14_vc15 opencv 安装包 ...
由于官网没有提供opencv_python‑3.4.7+contrib‑cp37‑cp37m‑win_amd64.whl的下载了,可以通过先下载opencv_python-3.4.7-cp37-cp37m-win_amd64....pip install --user opencv-contrib-python==3.4.7.28 两步实现
Hands-On-GPU-Accelerated-Computer-Vision-with-OpenCV-and-CUDA-master源代码
适用于Windows64位,对应Python 3.6版本,OpenCV为3.4.1.15版本;内含有《opencv_contrib_python-3.4.1.15-cp36-cp36m-win_amd64.whl》和《opencv_python-3.4.1.15-cp36-cp36m-win_amd64.whl》两个文件