寻找直线的方法
实际项目中需要寻找这些线段的端点:

1、首先对图片进行细化操作,这样获得直线还是比较清晰的。

2、在使用霍夫变换直线检测的时候,根据本图的先验知识,那就是直线在交点位置产生了急剧的变化,所以调大其第3参数,也就是角度变化。

下一步就可以进行端点检测。这里绘制出目前检测出来的端点:

端点的检测,需要比对的是每一个端点的相对位置。一般来说,我都选用更加靠近中间位置的端点作为结果。
void thin(const Mat &src, Mat &dst, const int iterations = 100);//Mat 需要为DEPTH_8U型二值图 //将 DEPTH_8U型二值图像进行细化 经典的Zhang并行快速细化算法 //细化算法 void thin(const Mat &src, Mat &dst, const int iterations) { const int height = src.rows - 1; const int width = src.cols - 1; //拷贝一个数组给另一个数组 if (src.data != dst.data) src.copyTo(dst); int n = 0, i = 0, j = 0; Mat tmpImg; uchar *pU, *pC, *pD; bool isFinished = false; for (n = 0; n < iterations; n++) { dst.copyTo(tmpImg); isFinished = false; //一次 先行后列扫描 开始 //扫描过程一 开始 for (i = 1; i < height; i++) { pU = tmpImg.ptr<uchar>(i - 1); pC = tmpImg.ptr<uchar>(i); pD = tmpImg.ptr<uchar>(i + 1); for (int j = 1; j < width; j++) { if (pC[j] > 0) { int ap = 0; int p2 = (pU[j] > 0); int p3 = (pU[j + 1] > 0); if (p2 == 0 && p3 == 1) ap++; int p4 = (pC[j + 1] > 0); if (p3 == 0 && p4 == 1) ap++; int p5 = (pD[j + 1] > 0); if (p4 == 0 && p5 == 1) ap++; int p6 = (pD[j] > 0); if (p5 == 0 && p6 == 1) ap++; int p7 = (pD[j - 1] > 0); if (p6 == 0 && p7 == 1) ap++; int p8 = (pC[j - 1] > 0); if (p7 == 0 && p8 == 1) ap++; int p9 = (pU[j - 1] > 0); if (p8 == 0 && p9 == 1) ap++; if (p9 == 0 && p2 == 1) ap++; if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > 1 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < 7) { if (ap == 1) { if ((p2*p4*p6 == 0) && (p4*p6*p8 == 0)) { dst.ptr<uchar>(i)[j] = 0; isFinished = true; } } } } } //扫描过程一 结束 dst.copyTo(tmpImg); //扫描过程二 开始 for (i = 1; i < height; i++) { pU = tmpImg.ptr<uchar>(i - 1); pC = tmpImg.ptr<uchar>(i); pD = tmpImg.ptr<uchar>(i + 1); for (int j = 1; j < width; j++) { if (pC[j] > 0) { int ap = 0; int p2 = (pU[j] > 0); int p3 = (pU[j + 1] > 0); if (p2 == 0 && p3 == 1) ap++; int p4 = (pC[j + 1] > 0); if (p3 == 0 && p4 == 1) ap++; int p5 = (pD[j + 1] > 0); if (p4 == 0 && p5 == 1) ap++; int p6 = (pD[j] > 0); if (p5 == 0 && p6 == 1) ap++; int p7 = (pD[j - 1] > 0); if (p6 == 0 && p7 == 1) ap++; int p8 = (pC[j - 1] > 0); if (p7 == 0 && p8 == 1) ap++; int p9 = (pU[j - 1] > 0); if (p8 == 0 && p9 == 1) ap++; if (p9 == 0 && p2 == 1) ap++; if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > 1 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < 7) { if (ap == 1) { if ((p2*p4*p8 == 0) && (p2*p6*p8 == 0)) { dst.ptr<uchar>(i)[j] = 0; isFinished = true; } } } } } } //一次 先行后列扫描完成 //如果在扫描过程中没有删除点,则提前退出 if (isFinished == false) break; } } } // end of thin int main() { RNG rng = RNG(12345); //随机数 Mat src = imread("f:/template/lines.png"); Mat gray; Mat bin; Mat matThin; cvtColor(src, gray, COLOR_BGR2GRAY); threshold(gray, bin, 0, 255, THRESH_BINARY_INV); thin(bin, matThin); imshow("matThin", matThin);//展示提取的边缘 vector<Vec4f> lines;//存储直线的容器 Mat dst = Mat(src.size(), src.type(), Scalar(255, 255, 255));//创建大小和类型都与源图像相同的背景为白色的图像 HoughLinesP(matThin, lines, 1, CV_PI / 180, 60, 0, 8);//霍夫变换直线检测 for (int i = 0; i < lines.size(); i++) { Scalar lineColor = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)); Vec4f l = lines[i]; line(dst, Point(l[0], l[1]), Point(l[2], l[3]), lineColor, 3, LINE_AA);//在创建的白色图像上画直线 circle(src, Point(l[0], l[1]), 3,Scalar(0,0,255), 2); circle(src, Point(l[2], l[3]), 3,Scalar(0,255,0), 1); } int i = 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了