Hough变换检测直线
来源:互联网 发布:pfordelta算法 编辑:程序博客网 时间:2024/05/15 23:48
直线的霍夫变换:
霍夫空间极坐标与图像空间的转换公式:
p = y * sin(theta) + x * cos(theta);
之后遍历图像的每个坐标点,每个坐标点以一度为增量,求取对应的p值,存入数组中,查找数组中数目大于一定阈值的p和theta,再在图像空间中把 直线 恢复出来
霍夫变换就是把图像左边空间上的线段转换到霍夫空间一个点,然后通过点的数目多少来确定是否为一条线段(但是画出的结果为一条直线)
实现代码如下:
#include <iostream>#include "gdal_priv.h"#include <string>using namespace std;//图像的膨胀//算法的实现依然有重复的地方,会造成空间和时间上的浪费,但是效果还可以,暂定如此,如有好的算法再进行改进void Expand(unsigned char* date,unsigned char* ExpandImage,int Width,int Height){ int x, y; int Direction[8][2] = {-1, -1, 0, -1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, -1, 0}; int Index; for(int i = 1;i < Height - 1;++i) { for(int j = 1;j < Width - 1;++j) { if(date[i * Width + j] == 255) { for(int k = 0;k < 8;++k) { x = i + Direction[k][0]; y = j + Direction[k][1]; Index = x * Width + y; ExpandImage[Index] = 255; } } } } return;}//图像的腐蚀void Erosion(unsigned char* date,unsigned char* ErosionImage,int Width,int Height){ int x, y; int Direction[8][2] = {-1, -1, 0, -1, 1, -1, 1, 0, 1, 1, 0, 1, -1, 1, -1, 0}; int Index; for(int i = 1;i < Height - 1;++i) { for(int j = 1;j < Width - 1;++j) { if(date[i * Width + j] == 0) { for(int k = 0;k < 8;++k) { x = i + Direction[k][0]; y = j + Direction[k][1]; Index = x * Width + y; ErosionImage[Index] = 0; } } } } return;}//图像相减求边界void Subtraction(unsigned char* ResultImage,unsigned char* leftImage,unsigned char* rightImage,int Width,int Height){ int Index; for(int i = 0;i < Height;++i) for(int j = 0;j < Width;++j) { Index = i * Width + j; ResultImage[Index] = leftImage[Index] - rightImage[Index]; } return ;}void FindBoundary(unsigned char* image,unsigned char* tempImage,int Width,int Height){ //生成对于图像膨胀的图像 unsigned char* ExpandImage = new unsigned char[Width * Height]; memset(ExpandImage,0,sizeof(unsigned char) * Width * Height); Expand(image ,ExpandImage,Width ,Height); Subtraction(tempImage,ExpandImage,image,Width,Height);}/************************************************************************** 直线的Hough检测* 参数:image0为原图形,image1为边缘检测结果,w、h为图像的宽和高* 由于得到的Hough变换结果图像与原图像大小不同,为了得到新的宽高信息* w、h使用引用类型*************************************************************************/unsigned char** HoughLine(unsigned char* image0, unsigned char* &tempImage, int &Width, int &Height,int scale=1){ //定义三角函数表 double sinValue[360]; double cosValue[360]; int i,x,y; int k = 100; int p = (int)(sqrt((double)(Width * Width + Height * Height) + 1)); //计算对角线长度 //申请临时存储空间 用来保存边缘检测结果// tempImage = new unsigned char[Width * Height]; memset(tempImage,0,sizeof(unsigned char) * Width * Height); //边缘检测// SideGrandiant(image0, tempImage, Width, Height); FindBoundary(image0, tempImage, Width, Height);// //根据Hough变换结果图的大小 重新为输出图象分配空间// if(image1 != NULL) // delete image1;////// image1 = (BYTE*)malloc(sizeof(BYTE)*p*360*4);//// image1 = new unsigned char[p * 360];// memset(image1,0,p * 360); //将图像转换为矩阵形式// BYTE** HoughBuf =CreatImage(image1,360,p); unsigned char** HoughBuf = new unsigned char* [p]; for(int i = 0;i < p;++i) { HoughBuf[i] = new unsigned char[360]; memset(HoughBuf[i],0,sizeof(unsigned char) * 360); //HoughBuf[i] = image1 + i * 360; } //for(int i = 0;i < p;++i) //{ // for(int j = 0;j < 360;++j) // HoughBuf[i][j] = image1[i * 360 + j]; //} //计算三角函数表 for(i=0; i<360 ; i++) { sinValue[i] = sin(i*3.1415926/180); cosValue[i] = cos(i*3.1415926/180); } int tp; //遍历原图象中的每个像素 for(y = 0; y < Height; y++) for(x = 0; x < Width; x++) { //对经过当前像素的任何直线区域进行检测 for(i = 0; i < 360; i++) { if( tempImage[(y * Width + x)] > k ) { tp = (int)( x * sinValue[i] + y * cosValue[i]); //忽略负数同时防止计数器溢出 if (tp < 0 || HoughBuf[tp][i] == 255) continue; HoughBuf[tp][i] += scale; } } } //重新设定图象大小 //Width = 360; //Height = p;// delete tempImage; return HoughBuf;}//画检测到的直线void DrawLine(unsigned char* LineIamge,int Width,int Height,int p,int theta){ double k,b; int x,y; if(theta != 90) //如果斜率存在 { //计算直线方程的参数 b = p / cos(theta * 3.1415926535 / 180); k = -sin(theta * 3.1415926535 / 180) / cos(theta * 3.1415926535 / 180); y=0; x=0; //斜率小于1的情况 if(abs(k) <= 1) { for(x = 0;x < Width;x++) { y=(int)(k * x + b); if(y >= 0 && y < Height) { LineIamge[y * Width + x] = 255; } } } //斜率大于1的情况 else { for(y = 0;y < Height;y++) { x = (int)(y / k - b / k); if(x >= 0 && x < Width) { /*imageBuf[y][x*4]=255; imageBuf[y][x*4+1]=0; imageBuf[y][x*4+2]=0; imageBuf[y][x*4+3]=255;*/ LineIamge[y * Width + x] = 255; } } } } //斜率不存在的情况 else { for(y = 0; y < Height;y++) { /*imageBuf[y][p*4]=255; imageBuf[y][p*4+1]=0; imageBuf[y][p*4+2]=0; imageBuf[y][p*4+3]=255;*/ LineIamge[y * Width + p] = 255; } }}int main(){ GDALAllRegister(); CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO"); string str1="1.1.bmp"; string str2="1.2.tif"; string str3 = "1.3.tif"; GDALDataset* pInDataset=(GDALDataset*)GDALOpen(str1.data() ,GA_ReadOnly); if(pInDataset == nullptr) { cout<<"未找到输入图像"<<endl; getchar(); return 1; } int Width=pInDataset->GetRasterXSize(); int Height = pInDataset->GetRasterYSize(); int band = pInDataset->GetRasterCount(); double dGeoTrans[6]={}; pInDataset->GetGeoTransform(dGeoTrans); const char* cProjectionRef = pInDataset->GetProjectionRef(); unsigned char* Image = new unsigned char[Width * Height]; GDALRasterBand* pRasterBand = pInDataset->GetRasterBand(1); CPLErr err=pRasterBand->RasterIO(GF_Read ,0 ,0 ,Width ,Height ,Image ,Width ,Height ,GDT_Byte ,0,0); unsigned char* ResultImage = new unsigned char[Width * Height];//保存图像的边缘信息,通过膨胀后的图像减去原始图像得到的边缘图像,用来检测是否得到了边缘 //ResultImage = nullptr; //unsigned char** HoughBuf = nullptr; unsigned char** HoughBuf; HoughBuf = HoughLine(Image,ResultImage,Width,Height); GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("GTiff"); GDALDataset* pOutDataset = pDriver->Create("1.2.tif" ,Width ,Height ,1 ,GDT_Byte ,NULL); GDALRasterBand* pOutRasterband=pOutDataset->GetRasterBand(1); pOutRasterband->RasterIO(GF_Write ,0 ,0 ,Width ,Height ,ResultImage ,Width ,Height ,GDT_Byte ,0 ,0); int p = (int)(sqrt((double)(Width * Width + Height * Height) + 1)); //计算对角线长度 unsigned char* LineImage = new unsigned char[Width * Height]; memset(LineImage,0,sizeof(unsigned char) * Width * Height); if(HoughBuf != nullptr) for(int i = 0;i < p;++i) { for(int j = 0;j < 360;++j) { if(HoughBuf[i][j] > 200) //设置阈值为200,可自行设置 { cout<<(int)HoughBuf[i][j]<<" "; DrawLine(LineImage,Width,Height,i,j);//得到的结果为一条直线 } } cout<<"***************"<<endl; } GDALDriver* pLineDriver = GetGDALDriverManager()->GetDriverByName("GTiff"); GDALDataset* pOutLineDataset = pLineDriver->Create("1.3.tif" ,Width ,Height ,1 ,GDT_Byte ,NULL); GDALRasterBand* pOutLineRasterband=pOutLineDataset->GetRasterBand(1); pOutLineRasterband->RasterIO(GF_Write ,0 ,0 ,Width ,Height ,LineImage ,Width ,Height ,GDT_Byte ,0 ,0); delete Image; delete ResultImage; delete LineImage; for(int i = 0;i < p;++i) delete HoughBuf[i]; delete HoughBuf; GDALClose(pOutDataset); GDALClose(pInDataset); GDALClose(pOutLineDataset); GetGDALDriverManager()->DeregisterDriver(pDriver); GetGDALDriverManager()->DeregisterDriver(pLineDriver); system("pause"); return 0;}
0 0
- Hough变换检测直线
- Hough 变换检测直线
- Hough变换检测直线
- Hough变换直线检测
- hough变换检测直线
- Hough变换检测直线
- Hough变换直线检测
- Hough变换-直线检测
- Hough变换直线检测
- Hough变换检测直线
- Hough变换检测直线
- Hough变换检测直线
- Hough变换直线检测
- Hough变换检测直线
- 通过hough变换检测直线
- Hough 变换检测直线、圆
- Hough变换之直线检测
- Hough变换检测直线【转】
- 【DP 训练】Storage Keepers, UVa10163
- 深度学习工程师招聘
- 漏洞learning[安全大事记]
- MySQL快速入门
- Oracle 11g升级至11.2.0.3
- Hough变换检测直线
- Git典型工作流程
- 类定义,封装,构造方法,构造方法重载练习
- javaWeb项目用过滤器filter实现登陆成功后才能访问主页面,否则直接输入主页面的地址自动跳转到登陆界面
- MySql——查看数据库性能基本参数
- Xml 格式数据的生成和解析
- Round-robin 算法
- RadioGroup 的 RadioButton 选择改变字体颜色和背景颜色(通过XML设置)
- ubuntu下配置apache,php,mysql