基于梯度方向、极化变换和聚类算法的图像主特征直线检测

基于机器学习和图像处理的直线检测

代码主要思路

     1)借助类LSD直线检测,提取图像各个方向梯度;2)对像素中的各个梯度方向做极化变换;3)对计划变换后的结果进行聚类运算;4)对聚类运算结果,选取topK,进行极化反变换;5)对结果进行腐蚀+膨胀+滤波,进行结果整合;6)可根据图像的长度、斜率等进行配置筛选和去重。

代码结果以及下载地址:下载地址






主函数代码

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <string>
#include <vector>
#include "lsd.h"
#include <fstream>
#include <math.h>
#include <algorithm>
#include <Cstring>
#include <io.h>
#include<numeric>
#define PI 3.1415926using namespace std;
using namespace cv;typedef struct {image_double imgDouble;Mat imgSrc, imgPro;
}imageInfo;void listFiles(const char * dir);
imageInfo imageProcess(char * DIR, double scale);
int lineLengthThreshold(ntuple_list LS, double scale);
vector<float> getPolarLine(vector<float> p);
void connectLine(Mat imgPlot, vector<float> decarTopX0, vector<float> decarTopY0, vector<float> decarTopX1, vector<float> decarTopY1);
void HighPassFilterSobel(const Mat& image, Mat& result);void main()
{//生成图像索引char dir[20] = "images\\";listFiles(dir);ifstream imageIndex;imageIndex.open("imageIndex.txt");const int LINE = 200;char str[LINE];while (imageIndex.getline(str, LINE)) {char DIR[260] = "images\\";strcat_s(DIR, str);double scale = 0.8;imageInfo imgInfo = imageProcess(DIR, scale);image_double image = imgInfo.imgDouble;Mat img = imgInfo.imgPro;Mat imgPlot = imgInfo.imgSrc;imshow("imgPlot", imgPlot);ntuple_list ls0 = lsd(image);cout << "ls0->size:" << ls0->size << endl;int binNum = 60;vector<double> disNum(binNum, 0);double binLength = img.rows / binNum;//设置直线筛选长度int lineThreshold = lineLengthThreshold(ls0, scale);cout << "lineThreshold:" << lineThreshold << endl;//将笛卡尔坐标系点转到极坐标系vector<float> polarR, polarTheta, decarPointLocX0, decarPointLocY0, decarPointLocX1, decarPointLocY1;vector<float> indexStep;//记录累加的步长for (int i = 0; i < ls0->size; i++) {ls0->values[5 * i + 0] = (int)(ls0->values[5 * i + 0] / scale);ls0->values[5 * i + 1] = (int)(ls0->values[5 * i + 1] / scale);ls0->values[5 * i + 2] = (int)(ls0->values[5 * i + 2] / scale);ls0->values[5 * i + 3] = (int)(ls0->values[5 * i + 3] / scale);int x0 = ls0->values[5 * i + 0];int y0 = ls0->values[5 * i + 1];int x1 = ls0->values[5 * i + 2];int y1 = ls0->values[5 * i + 3];//线长筛选并记录float lineLength = sqrt((x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0));if (lineLength < lineThreshold) {continue;}//边缘筛选int xTemp = img.cols - 10;int yTemp = img.rows - 10;if ((x0 < 10 && x1 < 10) || (x0 > xTemp && x1 > xTemp) || (y0 < 10 && y1 < 10) || (y0 > yTemp && y1 > yTemp)) {continue;}Point pp0 = Point(x0, y0);Point pp1 = Point(x1, y1);line(img, pp0, pp1, Scalar(225, 0, 0), 2, 4);circle(img, pp0, 10, Scalar(0, 0, 0));circle(img, pp1, 10, Scalar(255, 255, 255));float tempIndexStep = lineLength / lineThreshold;//cout << "indexStep:" << tempIndexStep << endl;indexStep.push_back(tempIndexStep);decarPointLocX0.push_back(x0);decarPointLocY0.push_back(y0);decarPointLocX1.push_back(x1);decarPointLocY1.push_back(y1);//统一坐标系并记录vector<float> decarPoint;int x0Point = x0 - img.cols / 2;int y0Point = img.rows / 2 - y0;int x1Point = x1 - img.cols / 2;int y1Point = img.rows / 2 - y1;decarPoint.push_back(x0Point);decarPoint.push_back(y0Point);decarPoint.push_back(x1Point);decarPoint.push_back(y1Point);//获取极坐标并记录vector<float> polarPoint = getPolarLine(decarPoint);polarR.push_back(polarPoint[0]);polarTheta.push_back(polarPoint[1]);}float rThreshold = 15;float thetaThreshold = 0.1;//寻找各个值的聚类统计数量int totalLine = polarR.size();cout << "totalLine:" << totalLine << endl;vector<float> index(totalLine, 0);for (int i = 0; i < totalLine; i++) {for (int j = 0; j < totalLine; j++) {if (i == j) {continue;}float subpolarR = abs(polarR[i] - polarR[j]);float subpolarTheta = abs(polarTheta[i] - polarTheta[j]);if (subpolarR < rThreshold && subpolarTheta < thetaThreshold) {if (indexStep[j] != 0)index[i] = index[i] + indexStep[j];elseindex[i]++;}}}//寻找聚类区域最多的点的索引TOP1vector<float>::iterator maxIndex = max_element(index.begin(), index.end());cout << "------------------------------" << endl;cout << "max:" << *maxIndex << endl;int maxInd = distance(index.begin(), maxIndex);cout << "maxInd:" << maxInd << endl;//存储聚类最多点的坐标并画线TOP1vector<float> decarTop1X0, decarTop1Y0, decarTop1X1, decarTop1Y1;vector<int> setLabel(totalLine, 0);//0:该点未使用;1:该点已使用for (int i = 0; i < totalLine; i++) {float subpolarR = abs(polarR[i] - polarR[maxInd]);float subpolarTheta = abs(polarTheta[i] - polarTheta[maxInd]);if (subpolarR < rThreshold && subpolarTheta < thetaThreshold) {decarTop1X0.push_back(decarPointLocX0[i]);decarTop1Y0.push_back(decarPointLocY0[i]);decarTop1X1.push_back(decarPointLocX1[i]);decarTop1Y1.push_back(decarPointLocY1[i]);setLabel[i] = 1;Point pp0 = Point(decarPointLocX0[i], decarPointLocY0[i]);Point pp1 = Point(decarPointLocX1[i], decarPointLocY1[i]);//line(imgPlot, pp0, pp1, Scalar(255, 0, 0), 3, 4);}}connectLine(imgPlot, decarTop1X0, decarTop1Y0, decarTop1X1, decarTop1Y1);//寻找聚类区域第二多的点的索引TOP2int usedPointTop2 = 0;vector<float> secondIndex(totalLine, 0);//剔除第一大的元素后的存储位置for (int i = 0; i < totalLine; i++) {if (setLabel[i] == 0) {secondIndex[i] = index[i];usedPointTop2++;}elsesecondIndex[i] = 0;//cout << secondIndex[i] << "-";}if (usedPointTop2 < 4) {continue;}//cout << endl;vector<float>::iterator secondMaxIndex = max_element(secondIndex.begin(), secondIndex.end());cout << "------------------------------" << endl;cout << "secondMax:" << *secondMaxIndex << endl;int secondMaxInd = distance(secondIndex.begin(), secondMaxIndex);cout << "secondMaxInd:" << secondMaxInd << endl;//存储聚类第二多点的坐标并画线TOP2vector<float> decarTop2X0, decarTop2Y0, decarTop2X1, decarTop2Y1;for (int i = 0; i < totalLine; i++) {float subpolarR = abs(polarR[i] - polarR[secondMaxInd]);float subpolarTheta = abs(polarTheta[i] - polarTheta[secondMaxInd]);if (subpolarR < rThreshold && subpolarTheta < thetaThreshold && setLabel[i] == 0) {decarTop2X0.push_back(decarPointLocX0[i]);decarTop2Y0.push_back(decarPointLocY0[i]);decarTop2X1.push_back(decarPointLocX1[i]);decarTop2Y1.push_back(decarPointLocY1[i]);Point pp0 = Point(decarPointLocX0[i], decarPointLocY0[i]);Point pp1 = Point(decarPointLocX1[i], decarPointLocY1[i]);setLabel[i] = 1;//line(imgPlot, pp0, pp1, Scalar(0, 255, 0), 3, 4);}}connectLine(imgPlot, decarTop2X0, decarTop2Y0, decarTop2X1, decarTop2Y1);//寻找聚类区域第三多的点的索引TOP3int usedPointTop3 = 0;vector<float> thirdIndex(totalLine, 0);//剔除第一大和第二大的元素后的存储位置for (int i = 0; i < totalLine; i++) {if (setLabel[i] == 0) {thirdIndex[i] = secondIndex[i];usedPointTop3++;}elsethirdIndex[i] = 0;//cout << thirdIndex[i] << "-";}//cout << endl;if (usedPointTop3 < 4) {continue;}vector<float>::iterator thirdMaxIndex = max_element(thirdIndex.begin(), thirdIndex.end());cout << "------------------------------" << endl;cout << "thirdMax:" << *thirdMaxIndex << endl;int thirdMaxInd = distance(thirdIndex.begin(), thirdMaxIndex);cout << "thirdMaxInd:" << thirdMaxInd << endl;//存储聚类第三多点的坐标并画线TOP3vector<float> decarTop3X0, decarTop3Y0, decarTop3X1, decarTop3Y1;for (int i = 0; i < totalLine; i++) {float subpolarR = abs(polarR[i] - polarR[thirdMaxInd]);float subpolarTheta = abs(polarTheta[i] - polarTheta[thirdMaxInd]);if (subpolarR < rThreshold && subpolarTheta < thetaThreshold && setLabel[i] == 0) {decarTop3X0.push_back(decarPointLocX0[i]);decarTop3Y0.push_back(decarPointLocY0[i]);decarTop3X1.push_back(decarPointLocX1[i]);decarTop3Y1.push_back(decarPointLocY1[i]);Point pp0 = Point(decarPointLocX0[i], decarPointLocY0[i]);Point pp1 = Point(decarPointLocX1[i], decarPointLocY1[i]);setLabel[i] = 1;//line(imgPlot, pp0, pp1, Scalar(0, 0, 255), 3, 4);}}connectLine(imgPlot, decarTop3X0, decarTop3Y0, decarTop3X1, decarTop3Y1);//寻找聚类区域第四多的点的索引TOP4int usedPointTop4 = 0;vector<float> fourthIndex(totalLine, 0);//剔除第一大的元素后的存储位置for (int i = 0; i < totalLine; i++) {if (setLabel[i] == 0) {fourthIndex[i] = thirdIndex[i];usedPointTop4++;}elsefourthIndex[i] = 0;//cout << fourthIndex[i] << "-";}//cout << endl;vector<float>::iterator fourthMaxIndex = max_element(fourthIndex.begin(), fourthIndex.end());cout << "------------------------------" << endl;cout << "fourthMax:" << *fourthMaxIndex << endl;int fourthMaxInd = distance(fourthIndex.begin(), fourthMaxIndex);cout << "fourthMaxInd:" << fourthMaxInd << endl;if (usedPointTop4 < 4 || *fourthMaxIndex == 0) {continue;}//存储聚类第四多点的坐标并画线TOP4vector<float> decarTop4X0, decarTop4Y0, decarTop4X1, decarTop4Y1;for (int i = 0; i < totalLine; i++) {float subpolarR = abs(polarR[i] - polarR[fourthMaxInd]);float subpolarTheta = abs(polarTheta[i] - polarTheta[fourthMaxInd]);if (subpolarR < rThreshold && subpolarTheta < thetaThreshold && setLabel[i] == 0) {decarTop4X0.push_back(decarPointLocX0[i]);decarTop4Y0.push_back(decarPointLocY0[i]);decarTop4X1.push_back(decarPointLocX1[i]);decarTop4Y1.push_back(decarPointLocY1[i]);Point pp0 = Point(decarPointLocX0[i], decarPointLocY0[i]);Point pp1 = Point(decarPointLocX1[i], decarPointLocY1[i]);setLabel[i] = 1;//line(img, pp0, pp1, Scalar(0, 255, 255), 3, 4);}}connectLine(img, decarTop4X0, decarTop4Y0, decarTop4X1, decarTop4Y1);//寻找聚类区域第五多的点的索引TOP5int usedPointTop5 = 0;vector<float> fifthIndex(totalLine, 0);//剔除第一大的元素后的存储位置for (int i = 0; i < totalLine; i++) {if (setLabel[i] == 0) {fifthIndex[i] = fourthIndex[i];usedPointTop5++;}elsefifthIndex[i] = 0;//cout << fifthIndex[i] << "-";}//cout << endl;vector<float>::iterator fifthMaxIndex = max_element(fifthIndex.begin(), fifthIndex.end());cout << "------------------------------" << endl;cout << "fifthMax:" << *fifthMaxIndex << endl;int fifthMaxInd = distance(fifthIndex.begin(), fifthMaxIndex);cout << "fifthMaxInd:" << fifthMaxInd << endl;if (usedPointTop5 < 4 || *fifthMaxIndex == 0) {continue;}//存储聚类第五多点的坐标并画线TOP5vector<float> decarTop5X0, decarTop5Y0, decarTop5X1, decarTop5Y1;for (int i = 0; i < totalLine; i++) {float subpolarR = abs(polarR[i] - polarR[fifthMaxInd]);float subpolarTheta = abs(polarTheta[i] - polarTheta[fifthMaxInd]);if (subpolarR < rThreshold && subpolarTheta < thetaThreshold && setLabel[i] == 0) {decarTop5X0.push_back(decarPointLocX0[i]);decarTop5Y0.push_back(decarPointLocY0[i]);decarTop5X1.push_back(decarPointLocX1[i]);decarTop5Y1.push_back(decarPointLocY1[i]);Point pp0 = Point(decarPointLocX0[i], decarPointLocY0[i]);Point pp1 = Point(decarPointLocX1[i], decarPointLocY1[i]);setLabel[i] = 1;//line(img, pp0, pp1, Scalar(255, 0, 255), 3, 4);}}connectLine(img, decarTop5X0, decarTop5Y0, decarTop5X1, decarTop5Y1);char resultPath[200] = "resultPath//";strcat_s(resultPath, str);imwrite(resultPath, imgPlot);namedWindow("IMG", CV_WINDOW_AUTOSIZE);//resizeWindow("IMG", 600, 800);imshow("IMG", imgPlot);waitKey(1);}system("Pause");
}

基于梯度方向、极化变换和聚类算法的图像主特征直线检测相关推荐

  1. 【matlab】机器学习与人工智能期末课设,基于 K-means 聚类算法的图像区域分割系统

    基于 K-means 聚类算法的图像区域分割系统主要由两部分组成,分别是登录界面和主界面.用户登录模块负责用户的登录功能,用户输入账号和密码正确后,进入主界面,失败则跳出弹窗,提示用户登录失败.这是用 ...

  2. 【聚类算法】基于matlab划分法k-means聚类算法【含Matlab源码 1941期】

    一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[聚类算法]基于matlab划分法k-means聚类算法[含Matlab源码 1941期] 点击上面蓝色字体,直接付费下载,即可. 获取代码 ...

  3. 论文学习——一种基于DTW的符号化时间序列聚类算法

    文章目录 1 摘要 2 引言 2.1 类似的工作 SAX 2.2 本文成果 3 相关知识 3.1 极值点EP 成为关键点KP 的条件 3.2 DTW距离 3.3 基于Normal矩阵的谱平分法 4 本 ...

  4. python实现的基于NMF的多图聚类算法

    python实现的基于NMF的多图聚类算法的封装 代码均由论文复现 文章目录 python实现的基于NMF的多图聚类算法的封装 前言 参考论文 一.NMF 二.Mjnmf 总结 前言 怕忘记干了这个事 ...

  5. 【图像隐写】基于LSB+DWT+DCT三种算法实现图像和音频水印嵌入提取含Matlab源码

    1 简介 基于LSB+DWT+DCT三种算法实现图像和音频水印嵌入提取. 1.1 LSB算法 根据LSB算法简单易实现的特点,结合在图像置乱技术中很好特性的Arnold变换.利用变化产生影子图像.通过 ...

  6. 基于经典的机器学习k-means聚类算法实现对三通道图片的压缩操作

    https://www.toutiao.com/a6573221465104056846/ 压缩图片的原理 k-means算法实现图像的压缩是k-means聚类算法的一个经典的应用,它把一个彩色图压缩 ...

  7. 超详细!构建基于客户细分的 K-Means 聚类算法

    客群细分对于企业了解目标受众非常重要.根据受众群体的不同,我们可以给采取不同的营销策略.目前有许多无监督的机器学习算法可以帮助公司识别他们的用户群并创建消费群体. 在本文中,我将分享一种目前比较流行的 ...

  8. 基于 K-means 聚类算法实现图像区域分割matlab代码

    1 简介 对图像进行颜色区域分割.将图像转换到CIE L*a*b颜色空间,用K均值聚类分析算法对描述颜色的a*和b*通道进行聚类分析;通过提取各个颜色区域独立成为单色的新图像,对图像进行分割处理.实验 ...

  9. 【图像分割】基于 K-means 聚类算法实现图像区域分割matlab代码

    1 简介 对图像进行颜色区域分割.将图像转换到CIE L*a*b颜色空间,用K均值聚类分析算法对描述颜色的a*和b*通道进行聚类分析;通过提取各个颜色区域独立成为单色的新图像,对图像进行分割处理.实验 ...

最新文章

  1. 英特尔也决定了!正式退出5G智能型手机
  2. 【转】双代号网络图的绘制
  3. python-os创建文件夹-create_dir_if_not_exist.py
  4. sudo vi ~/etc/profile 报错E212:Can't open file for writing
  5. object picker 微信小程序_微信小程序 demo分享
  6. android aptx固件,新增aptX蓝牙发射协议,M5固件首次升级!
  7. Spring Cloud与微服务学习总结(11)——spring cloud-openFeign 声明式远程调用总结
  8. Java中static的作用详解_详解java中static关键词的作用
  9. 连续子数组的最大和(基于动态规划)
  10. boost.asio mysql_boost asio学习笔记
  11. Lightroom Classic 教程,如何将照片从 Lightroom 移至Ps,在 Ps 中为照片添加文本?
  12. python 新闻热点_基于Python的新闻API调用代码实例
  13. cognos报表制作学习(一)cognos如何新建普通的reportstudio报表
  14. 数据中台落地问题与建议-数字化架构设计(2)
  15. vs 2015 密钥
  16. 几个同步盘的使用体会
  17. 万能Ghost系统制作教程(龙帝国论坛)
  18. CVE: 2014-6271 Bash Specially-crafted Environment Variables Code Injection Vulnerability Analysis
  19. 关于分销体系是怎么理解的?
  20. 为什么很多人喜欢猫不喜欢狗

热门文章

  1. HDU 2084 数塔(DP)(JAVA版)
  2. Streamr助你掌控自己的数据(2)——三种整合数据至Streamr的典型场景
  3. 【BZOJ】3524 [POI2014] Couriers(主席树)
  4. svn官方备份hot-backup.py强烈推荐
  5. codeforces 165B(Burning Midnight Oil)
  6. jsp中九大内置对象
  7. 在VS中,如何新建项目,如何添加类库
  8. 利用委托和泛型实现树的常用操作
  9. 写《回国驯火记》的那个安普若
  10. 《OpenCV3编程入门》学习笔记2 启程前的认知准备