【问题标题】:Affine transform in C++C++中的仿射变换
【发布时间】:2016-12-13 17:01:46
【问题描述】:

我目前正在使用 Open CV 3.1 在 Visual Studio 2013 中为学校制作一个图像处理项目。我的目标(目前)是使用仿射变换来变换图像,以便将梯形板变换为矩形。

为此,我减去了某些通道并对图像进行了阈值处理,这样现在我就有了一个二值图像,在板的角落有白色块。 现在我需要选择最接近每个角的 4 个白点,并(使用仿射变换)将它们设置为变换图像的角。

因为这是我第一次使用 Open CV,所以我被卡住了。

这是我的代码:

#include <iostream>
#include <opencv2\core.hpp>
#include <opencv2\highgui.hpp>
#include<opencv2/imgproc.hpp>
#include <stdlib.h>
#include <stdio.h>
#include <vector>


int main(){

    double dist;
    cv::Mat image;
    image = cv::imread("C:\\Users\\...\\ideal.png");

    cv::Mat imagebin;
    imagebin = cv::imread("C:\\Users\\...\\ideal.png");

    cv::Mat imageerode;

    //cv::imshow("Test", image);

    cv::Mat src = cv::imread("C:\\Users\\...\\ideal.png");
    std::vector<cv::Mat>img_rgb;
    cv::split(src, img_rgb);

    //cv::imshow("ideal.png", img_rgb[2] - img_rgb[1]);

    cv::threshold(img_rgb[2] - 0.5*img_rgb[1], imagebin , 20, 255, CV_THRESH_BINARY);
    cv::erode(imagebin, imageerode, cv::Mat(), cv::Point(1, 1), 2, 1, 1);
    cv::erode(imageerode, imageerode, cv::Mat(), cv::Point(1, 1), 2, 1, 1);

    //  cv::Point2f array[4];
    //  std::vector<cv::Point2f> array;

    for (int i = 0; i < imageerode.cols; i++)
    {
        for (int j = 0; j < imageerode.rows; j++)
        {
            if (imageerode.at<uchar>(i,j) > 0)
            {
                dist = std::min(dist, i + j);
            }
        }
    }

    //cv::imshow("Test binary", imagebin);
    cv::namedWindow("Test", CV_WINDOW_NORMAL);
    cv::imshow("Test", imageerode);
    cv::waitKey(0);

    std::cout << "Hello world!";
    return 0;
}

如您所见,我不知道如何使用 image.at 遍历每个白色像素并保存到每个角落的距离。

我将不胜感激。

另外:我不想这样做。我真的很想学习如何做到这一点。但我现在有些心不在焉。

谢谢

编辑:

我想我已经找到 4 个点的坐标了。但我无法真正理解 warpAffine 语法。

代码:

for (int i = 0; i < imageerode.cols; i++)
{
    for (int j = 0; j < imageerode.rows; j++)
    {
        if (imageerode.at<uchar>(i, j) > 0)
        {

            if (i + j < distances[0])
            {
                distances[0] = i + j;
                coordinates[0] = i;
                coordinates[1] = j;
            }

            if (i + imageerode.cols-j < distances[1])
            {
                distances[1] = i + imageerode.cols-j;
                coordinates[2] = i;
                coordinates[3] = j;
            }

            if (imageerode.rows-i + j < distances[2])
            {
                distances[2] = imageerode.rows - i + j;
                coordinates[4] = i;
                coordinates[5] = j;
            }

            if (imageerode.rows-i + imageerode.cols-j < distances[3])
            {
                distances[3] = imageerode.rows - i + imageerode.cols - j;
                coordinates[6] = i;
                coordinates[7] = j;
            }

        }
    }

我将所有距离值设置为 imageerode.cols+imageerode.rows,因为它是它可以获得的最大值。 另外:请注意,我使用的是出租车几何。有人告诉我它更快,结果几乎相同。

如果有人可以帮助我处理 warpAffine,那就太好了。我不明白我把找到的坐标放在哪里。

谢谢

【问题讨论】:

  • 试试findContours
  • 寻找角落怎么样?遍历所有边界像素(黑色与相邻的白色像素)并查看相邻边界像素是否转弯(即急转弯,您可能会发现没有干净的方法来检测接近 180 的转弯°)。然后你必须转角并且可以很容易地找到最近的白色像素。或者直接处理角落。
  • 学校里的visual c ....很酷(也许)
  • 有人告诉我,我必须找到这 4 点。而且我不确定如何循环。我理解逻辑:我遍历每个像素并获取到每个角落的距离,然后与我得到的距离值进行比较并选择较小的那个。但我不知道语法 - 如何编码。有什么帮助吗?

标签: c++ visual-studio-2013 affinetransform opencv3.1


【解决方案1】:

我不确定您的“梯形板”的外观如何,但如果它具有透视变换(例如使用相机捕捉矩形时),那么仿射变换是不够的。使用透视变换。我认为Features2D + Homography to find a known object 非常接近您想要做的事情。

【讨论】:

  • 这正是我所说的梯形板的意思。而且我认为仿射变换可能还不够,但我必须在这个练习中使用这个变换。
猜你喜欢
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 2013-07-04
  • 1970-01-01
相关资源
最近更新 更多