本节主要参考opencv源码,初步了解了hough变换直线检测。
#include "houghLine.h"
static vector<CvLinePolar> houghLineStandard(const Mat& img, float rho, float theta, int threshold, int lineMax)
{
const uchar* image;
int step;
int width;
int height;
float irho = 1 / rho;
double scale;
int total = 0;
image = img.data;
step = img.step;
width = img.cols;
height = img.rows;
//角度和半径分为多少段
int numangle = int(CV_PI / theta);
int numrho = int((width + height + 1) / rho);
int* accum = (int*)malloc(sizeof(int) * (numangle + 2) * (numrho + 2));
int* sort_buf = (int*)malloc(sizeof(int) * (numangle * numrho));
memset(accum,0,sizeof(accum[0]) * (numangle + 2) * (numrho + 2));
float *tabSin = (float*)malloc(numangle * sizeof(float));
float *tabCos = (float*)malloc(numangle * sizeof(float));
//求sin(theta), cos(theta)
float ang = 0;
for (int n = 0; n < numangle; ang += theta, n++)
{
tabSin[n] = float(sin((double)ang) * irho);
tabCos[n] = float(cos((double)ang) * irho);
}
//计算直线出现频率
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (image[i * step + j] != 0)
{
for (int n = 0; n < numangle; n++)
{
//极坐标系下对应点进行统计直线频数
int r = int(j * tabCos[n] + i * tabSin[n]);//这里p有可能为负数
r = abs(r);//将p原点移动到中心
accum[r * (numangle + 2) + n]++;
}
}
}
}
//极大值抑制
for (int r = 0; r < numrho; r++)
{
for (int n = 2; n < numangle; n++)
{
int base = r * (numangle + 2) + n;
if (accum[base] > threshold &&
accum[base] > accum[base - 1] && accum[base] >= accum[base + 1] &&
accum[base] > accum[base - numrho - 2] && accum[base] >= accum[base + numrho + 2])
sort_buf[total++] = base;
}
}
//返回符合条件的直线
vector<CvLinePolar> m_Lines;
scale = 1. / (numrho + 2);
for (int i = 0; i < total; i++)
{
CvLinePolar Line;
int idx = sort_buf[i];
Line.angle = idx % (numangle + 2);
Line.rho = idx / (numangle + 2);
m_Lines.push_back(Line);
}
return m_Lines;
}
#ifndef _HOUGHLINE_H_
#define _HOUGHLINE_H_
#include <iostream>
#include <opencv2\opencv.hpp>
using namespace std;
using namespace cv;
typedef struct CvLinePolar
{
float rho;
float angle;
}CvLinePolar;
static vector<CvLinePolar> houghLineStandard(const Mat& img, float rho, float theta, int threshold, int lineMax);
#endif;