代码实现:
int main()
{
cv::Mat image = cv::imread("1.jpg", 0);
if (image.empty()) return -1;
//图像尺寸转换
const int nrows = image.rows, ncols = image.cols;
//获取DFT尺寸
int crows = cv::getOptimalDFTSize(nrows), ccols = cv::getOptimalDFTSize(ncols);
//复制图层,超过边界区域填充为0
cv::Mat result;
cv::copyMakeBorder(image, result, 0, crows - nrows, 0, ccols - ncols, cv::BORDER_CONSTANT, cv::Scalar(0));
//为傅里叶变换的结果(实部和虚部)分配存储空间
cv::Mat groupMat[] = { cv::Mat_<float>(result), cv::Mat::zeros(result.size(), CV_32F) };
//通道合并
cv::Mat mergeMat;
cv::merge(groupMat, 2, mergeMat);
//DFT变换
cv::dft(mergeMat, mergeMat);
//分离通道
cv::split(mergeMat, groupMat);
//计算幅值
cv::magnitude(groupMat[0], groupMat[1], groupMat[0]);
cv::Mat dftresult;
dftresult = groupMat[0].clone();
//对数变换
dftresult += 1;
cv::log(dftresult, dftresult);
//裁剪幅度图
dftresult = dftresult(cv::Rect(0, 0, ncols, nrows));
//归一化
cv::normalize(dftresult, dftresult, 0, 1, CV_MINMAX);
//图像类型转换
//输出图像类型,尺寸缩放因子,尺寸偏移量
dftresult.convertTo(dftresult, CV_8UC1, 255, 0);
//中心变换
int cx = dftresult.cols / 2, cy = dftresult.rows / 2;
cv::Mat tmp;
//Top-Left-为每个象限创建ROI
cv::Mat q0(dftresult, cv::Rect(0, 0, cx, cy));
//Bottom-Left
cv::Mat q1(dftresult, cv::Rect(0, cy, cx, cy));
//Top-Right
cv::Mat q2(dftresult, cv::Rect(cx, 0, cx, cy));
//Bottom-right
cv::Mat q3(dftresult, cv::Rect(cx, cy, cx, cy));
q0.copyTo(tmp), q3.copyTo(q0), tmp.copyTo(q3);
q1.copyTo(tmp), q2.copyTo(q1), tmp.copyTo(q2);
cv::imshow("dftresult", dftresult);
//固定阈值二值化
cv::Mat binaryMat;
cv::threshold(dftresult, binaryMat, 122, 255, CV_THRESH_BINARY);
cv::imshow("binaryMat", binaryMat);
//霍夫变换
//输入图像,输出线向量(线向量由两个元素组成,第一个是距离原点的距离,第二个是线旋转角)
//累积像素的距离分辨率,累积弧度的角度分辨率
//要检测一条直线所需最少的曲线交点
//多尺度霍夫变换参数,是一个距离分辨率因子
std::vector<cv::Vec2f> lines;
cv::HoughLines(binaryMat, lines, 1, CV_PI / 180, 100, 0, 0);
//检测线个数
std::cout << lines.size() << std::endl;
//绘制检测线
cv::Mat houghMat(binaryMat.size(), CV_8UC3);
for (int i = 0; i < lines.size(); i++)
{
float rho = lines[i][0], theta = lines[i][1];
cv::Point pt1, pt2;
//坐标变换生成线表达式
doub