c++ - 如何在 OpenCV 中找到菱形角并从中裁剪出较小的矩形?

标签 c++ opencv crop rect corner-detection

我愿意从扭曲的图像中得到一个简单的矩形。

例如,一旦我有这样的图像: enter image description here

...我想裁剪与以下矩形相对应的区域: enter image description here

...但是我的代码正在提取这个更大的框架: enter image description here

我的代码如下所示:

int main(int argc, char** argv) {
    cv::Mat img = cv::imread(argv[1]);

    // Convert RGB Mat to GRAY
    cv::Mat gray;
    cv::cvtColor(img, gray, CV_BGR2GRAY);

    // Store the set of points in the image before assembling the bounding box
    std::vector<cv::Point> points;
    cv::Mat_<uchar>::iterator it = gray.begin<uchar>();
    cv::Mat_<uchar>::iterator end = gray.end<uchar>();
    for (; it != end; ++it) {
        if (*it)
            points.push_back(it.pos());
    }

    // Compute minimal bounding box
    Rect box = cv::boundingRect(cv::Mat(points));

    // Draw bounding box in the original image (debug purposes)
    cv::Point2f vertices[4];
    vertices[0] = Point2f(box.x, box.y  +box.height);
    vertices[1] = Point2f(box.x, box.y);
    vertices[2] = Point2f(box.x+ box.width, box.y);
    vertices[3] = Point2f(box.x+ box.width, box.y   +box.height);

    for (int i = 0; i < 4; ++i) {
        cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA);
        cout << "==== vertices (x, y) = " << vertices[i].x << ", " << vertices[i].y << endl;
    }

    cv::imshow("box", img);
    cv::imwrite("box.png", img);

    waitKey(0);

    return 0;
}

关于如何找到菱形角并尝试将它们缩小为较小的矩形有什么想法吗?

最佳答案

这个问题最困难的部分实际上是找到菱形角的位置。如果您实际使用的图像与示例有很大不同,则这种查找菱形角的特定过程可能不起作用。完成此操作后,您可以根据角点与图像中心的距离对角点进行排序。您正在寻找最接近图像中心的点。

首先,您必须定义一个用于排序比较的仿函数(如果您可以使用 C++11,这可以是 lambda):

struct CenterDistance
{
    CenterDistance(cv::Point2f pt) : center(pt){}

    template <typename T> bool operator() (cv::Point_<T> p1, cv::Point_<T> p2) const
    {
        return cv::norm(p1-center) < cv::norm(p2-center);
    }

    cv::Point2f center;
};

这实际上不需要是模板化的 operator(),但它使其适用于任何 cv::Point_ 类型。

对于您的示例图像,图像角点定义得很好,因此您可以使用 FAST 等角点检测器。然后,您可以使用cv::convexHull()来获取外部点,这些点应该只是菱形角。

int main(int argc, char** argv) {
    cv::Mat img = cv::imread(argv[1]);

    // Convert RGB Mat to GRAY
    cv::Mat gray;
    cv::cvtColor(img, gray, CV_BGR2GRAY);

    // Detect image corners
    std::vector<cv::KeyPoint> kpts;
    cv::FAST(gray, kpts, 50);

    std::vector<cv::Point2f> points;
    cv::KeyPoint::convert(kpts, points);
    cv::convexHull(points, points);

    cv::Point2f center(img.size().width / 2.f, img.size().height / 2.f);
    CenterDistance centerDistance(center);
    std::sort(points.begin(), points.end(), centerDistance);

    //The two points with minimum distance are what we want
    cv::rectangle(img, points[0], points[1], cv::Scalar(0,255,0));

    cv::imshow("box", img);
    cv::imwrite("box.png", img);

    cv::waitKey(0);

    return 0;
}

请注意,您可以使用 cv::rectangle() 而不是从线条构造绘制的矩形。结果是:

Box result

关于c++ - 如何在 OpenCV 中找到菱形角并从中裁剪出较小的矩形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17581268/

相关文章:

c++ - Visual Studio 中的静态和动态链接

Android:拉伸(stretch)和裁剪图像(但保持纵横比)

c++ - 我使用统一内存运行内核函数后无法访问它

c++ - 为函数参数创建静态而不是临时的

opencv - 二值图像中圆盘的半径

python - 如何计算10张图片相同像素的平均值?

css - 如何使方形裁剪图像响应

javascript - 搜索没有jquery的js图像裁剪插件

c++ - 如何构建 boost 静态库?

c++ - MFC 文档模板中的共享处理程序预处理器指令