怪力豆 2024-05-19 15:52 采纳率: 83.3%
浏览 1
已结题

DFT+霍夫直线检测完成旋转图像校正

问题:在下面的代码中为什么要进行float angelT = nRows* tan(theta/180*CV_PI)/nCols;这样的角度转换?我不明白这个公式的是怎么得出的?


```c++
          int nRows = grayImg.rows;
          int nCols = grayImg.cols;
          std::cout << "srcImage row:" << nRows << std::endl;
          std::cout << "srcImage col:" << nCols << std::endl;
          // 获取DFT尺寸
          int cRows = cv::getOptimalDFTSize(nRows);
          int cCols = cv::getOptimalDFTSize(nCols);
          std::cout << "DFTImage row:" << cRows << std::endl;
          std::cout << "DFTImage col:" << cCols << std::endl;
          cv::Mat sizeConvMat;
          copyMakeBorder(grayImg, sizeConvMat, 0, cRows -nRows, 0,
             cCols-nCols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
          //  通道组建立,
          cv::Mat groupMats[] = {cv::Mat_<float>(sizeConvMat),
               cv::Mat::zeros(sizeConvMat.size(), CV_32F)};
          cv::Mat mergeMat;
          // 通道合并
          merge(groupMats,2,mergeMat);
          // DFT变换
          dft(mergeMat, mergeMat);
          // 分离通道
          split(mergeMat, groupMats);
          // 计算幅值
          magnitude(groupMats[0], groupMats[1], groupMats[0]);
          cv::Mat magnitudeMat = groupMats[0].clone();
          // 归一化操作
          magnitudeMat += Scalar::all(1);
          log(magnitudeMat, magnitudeMat);
          normalize(magnitudeMat, magnitudeMat, 0, 1, CV_MINMAX);
          magnitudeMat.convertTo(magnitudeMat,CV_8UC1,255,0);
          // 中心平移
          int cx = magnitudeMat.cols/2;
          int cy = magnitudeMat.rows/2;
          Mat tmp;
          // Top-Left - 为每一个象限创建ROI
          Mat q0(magnitudeMat,Rect(0,0,cx,cy));
          // Top-Right
          Mat q1(magnitudeMat,Rect(cx,0,cx,cy));
          // Bottom-Left
          Mat q2(magnitudeMat,Rect(0,cy,cx,cy));
          // Bottom-Right
          Mat q3(magnitudeMat,Rect(cx,cy,cx,cy));
          // 交换象限 (Top-Left with Bottom-Right)
          q0.copyTo(tmp);
          q3.copyTo(q0);
          tmp.copyTo(q3);
          // 交换象限 (Top-Right with Bottom-Left)
          q1.copyTo(tmp);
          q2.copyTo(q1);
          tmp.copyTo(q2);
          //cv::imshow("magnitudeMat2", magnitudeMat);

          // 固定阈值二值化处理
          cv::Mat binaryMagnMat;
          threshold(magnitudeMat,binaryMagnMat,132,255,CV_THRESH_BINARY);
          //cv::imshow("binaryMagnMat", binaryMagnMat);
          // 霍夫变换
          std::vector<Vec2f> lines;
          binaryMagnMat.convertTo(binaryMagnMat,CV_8UC1,255,0);
          HoughLines(binaryMagnMat, lines, 1, CV_PI/180, 100, 0, 0 );

          float theta = 0;
          // 检测线角度判断
          for( size_t i = 0; i < lines.size(); i++ )
          {
            float  thetaTemp = lines[i][1]*180/CV_PI;
            if(thetaTemp > 0 && thetaTemp < 90)
            {
                theta = thetaTemp;
                break;
            }
          }
          // 角度转换
          float angelT = nRows* tan(theta/180*CV_PI)/nCols;
          theta = atan(angelT)*180/CV_PI;
          std::cout << "theta:" << theta << std::endl;

        // 取图像中心
        cv::Point2f centerPoint = cv::Point2f(nCols/2, nRows/2);
        double scale = 1;//不进行缩放
        // 计算旋转矩阵
        cv::Mat warpMat = getRotationMatrix2D(centerPoint, theta, scale);
        // 仿射变换
        cv::Mat resultImage(grayImg.size(), grayImg.type());
        cv::warpAffine(grayImg, resultImage,
          warpMat, resultImage.size());
        //imshow("resultImage",resultImage);
        cvtColor(resultImage, outputImage, CV_GRAY2BGR);

```

  • 写回答

3条回答 默认 最新

  • 阿里嘎多学长 2024-05-19 15:53
    关注

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    您想要解决的问题

    您的提问目的是要理解在OpenCV中进行DFT(离散傅里叶变换)和霍夫直线检测后,为什么要进行特定的角度转换计算,以及这个转换公式是如何得出的。

    问题出现原因

    在图像处理中,DFT通常用于频域分析,而霍夫变换用于检测图像中的直线。当使用霍夫变换检测到直线后,可能需要对图像进行旋转校正,以确保直线在图像中是水平或垂直的。角度转换的目的是计算出旋转图像所需的角度,以便进行校正。

    问题解决方案

    角度转换的公式 float angelT = nRows* tan(theta/180*CV_PI)/nCols; 是用来计算图像旋转所需的正切值。这个公式的推导基于图像旋转的几何关系。当图像以角度 theta 旋转时,图像的每行都会以不同的比例因子进行缩放,这个比例因子取决于旋转角度和图像的尺寸。

    具体来说,公式中的 tan(theta/180*CV_PI) 是将角度 theta 从度转换为弧度,并计算正切值。然后,这个正切值乘以图像的行数 nRows 并除以图像的列数 nCols,得到一个缩放因子 angelT,它表示旋转后图像每行相对于原始图像每行的缩放比例。

    提供代码

    以下是修改后的代码,包括角度转换的解释和旋转图像的实现:

    // ... 省略之前的代码 ...
    
    // 检测线角度判断
    float theta = 0;
    for(size_t i = 0; i < lines.size(); i++)
    {
        float thetaTemp = lines[i][1] * 180 / CV_PI;
        if(thetaTemp > 0 && thetaTemp < 90)
        {
            theta = thetaTemp;
            break;
        }
    }
    
    // 角度转换,计算旋转缩放因子
    float angelT = nRows * tan(theta * CV_PI / 180) / nCols;
    theta = atan(angelT) * 180 / CV_PI;
    std::cout << "theta: " << theta << std::endl;
    
    // 取图像中心
    cv::Point2f centerPoint = cv::Point2f(nCols / 2, nRows / 2);
    double scale = 1; // 不进行缩放
    // 计算旋转矩阵
    cv::Mat warpMat = getRotationMatrix2D(centerPoint, theta, scale);
    // 仿射变换
    cv::Mat resultImage(grayImg.size(), grayImg.type());
    cv::warpAffine(grayImg, resultImage, warpMat, resultImage.size());
    
    // ... 省略之后的代码 ...
    

    代码运行方式

    • 确保您的环境中安装了OpenCV库。
    • 将上述代码保存为 .cpp 文件,并使用支持C++11或更高版本的编译器进行编译。
    • 使用命令行运行编译后的程序。

    代码预期运行结果

    • 程序将显示旋转校正后的图像,其中检测到的直线将更加水平或垂直。

    推荐相关链接

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 5月27日
  • 已采纳回答 5月19日
  • 创建了问题 5月19日

悬赏问题

  • ¥200 csgo2的viewmatrix值是否还有别的获取方式
  • ¥15 Stable Diffusion,用Ebsynth utility在视频选帧图重绘,第一步报错,蒙版和帧图没法生成,怎么处理啊
  • ¥15 请把下列每一行代码完整地读懂并注释出来
  • ¥15 pycharm运行main文件,显示没有conda环境
  • ¥15 易优eyoucms关于二级栏目调用的问题
  • ¥15 寻找公式识别开发,自动识别整页文档、图像公式的软件
  • ¥15 为什么eclipse不能再下载了?
  • ¥15 编辑cmake lists 明明写了project项目名,但是还是报错怎么回事
  • ¥15 关于#计算机视觉#的问题:求一份高质量桥梁多病害数据集
  • ¥15 特定网页无法访问,已排除网页问题