如何在黑色区域OpenCV中找到矩形(C ++)

时间:2019-02-27 14:24:33

标签: c++ opencv

我是新手OpenCV。我正在使用opencv查找位置在图像中附加图章。该图章不能与图像中的其他对象重叠。

示例二进制图像,白色区域是图像上的对象,黑色区域是无对象 Example image

结果:在黑色区域(白色圆圈)中找到矩形可以附加图章 Result imagge

请帮助我在黑色区域找到与蓝色矩形相同的矩形。 谢谢!

1 个答案:

答案 0 :(得分:1)

如果您知道矩形数,则可以使用kmeans作为聚类点。 首先只获得蓝点并将其二值化:

cv::Mat img = cv::imread("NQdmi.png", cv::IMREAD_COLOR);

std::vector<cv::Mat> chans;
cv::split(img, chans);

cv::Mat diff;
cv::absdiff(chans[2], chans[1], diff);

cv::threshold(diff, diff, 1, 255, cv::THRESH_BINARY);

cv::imshow("diff", diff);

仅蓝点:

Binarization result

聚类点并找到旋转的矩形:

std::vector<cv::Point2f> points;
for (int y = 0; y < diff.rows; ++y)
{
    for (int x = 0; x < diff.cols; ++x)
    {
        if (diff.at<uchar>(y, x))
        {
            points.emplace_back(x, y);
        }
    }
}

cv::Mat pointsKmeans(points.size(), 1, CV_32FC2, &points[0]);
cv::Mat labels;
int clusterCount = 2;
cv::Mat centers;

cv::kmeans(pointsKmeans, clusterCount, labels,
    cv::TermCriteria(cv::TermCriteria::EPS+cv::TermCriteria::COUNT, 100, 1.0),
       3, cv::KMEANS_PP_CENTERS, centers);

std::vector<cv::Point2f> points1;
std::vector<cv::Point2f> points2;

cv::Mat draw = img.clone();
for (size_t i = 0; i < points.size(); ++i)
{
    int clusterIdx = labels.at<int>(i);
    if (clusterIdx > 0)
    {
        cv::circle(draw, points[i], 2, cv::Scalar(255, 0, 0), cv::FILLED, cv::LINE_AA);
        points1.push_back(points[i]);
    }
    else
    {
        cv::circle(draw, points[i], 2, cv::Scalar(0, 0, 255), cv::FILLED, cv::LINE_AA);
        points2.push_back(points[i]);
    }
}

auto DrawRRect = [draw](const std::vector<cv::Point2f>& pp)
{
    cv::RotatedRect rr = cv::minAreaRect(pp);
    cv::Point2f corners[4];
    rr.points(corners);
    cv::line(draw, corners[0], corners[1], cv::Scalar(0, 255, 0), 2);
    cv::line(draw, corners[1], corners[2], cv::Scalar(0, 255, 0), 2);
    cv::line(draw, corners[2], corners[3], cv::Scalar(0, 255, 0), 2);
    cv::line(draw, corners[3], corners[0], cv::Scalar(0, 255, 0), 2);
};
DrawRRect(points1);
DrawRRect(points2);

cv::imshow("draw", draw);

结果:

Result