我正在尝试检测绘制在图像上的一些矩形(白色)。 (比如使用绘画或其他图像编辑工具)。 由于我是图像处理的初学者,我通过网络和 OpenCV 示例程序搜索来完成这项工作,但无法让它完美地工作。我正在使用 OpenCV C++ 库。
我试过的算法
cv::Mat src = cv::imread(argv[1]);
cv::Mat gray;
cv::cvtColor(src, gray, CV_BGR2GRAY);
meanStdDev(gray, mu, sigma);
cv::Mat bw;
cv::Canny(gray, bw, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0]);
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> approx;
for (int i = 0; i < contours.size(); i++){
cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.02, true);
if (approx.size() >= 4 && approx.size() <= 6)
Rect boundRect = boundingRect( Mat(approx) );
rectangle( dst, boundRect.tl(), boundRect.br(), Scalar(255,255,255), 1, 8, 0 );}
只检测到一个矩形。你能指导我或一些相同的链接吗?
输入图片:
输出图像:
最佳答案
我无法编译你的代码示例,因为 boundRect 是在 if block 中声明的,但矩形绘图(试图访问 boundRect)在 if block 之外,所以我调整了你的代码:
int main(int argc, char* argv[])
{
cv::Mat src = cv::imread("C:/StackOverflow/Input/rectangles.png");
cv::Mat dst = src.clone();
cv::Mat gray;
cv::cvtColor(src, gray, CV_BGR2GRAY);
// ADDED: missing declaration of mu and sigma
cv::Scalar mu, sigma;
meanStdDev(gray, mu, sigma);
cv::Mat bw;
cv::Canny(gray, bw, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0]);
// ADDED: displaying the canny output
cv::imshow("canny", bw);
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> approx;
for (int i = 0; i < contours.size(); i++){
cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.02, true);
if (approx.size() >= 4 && approx.size() <= 6)
{
// ADDED: brackets around both lines belonging to the if-block
cv::Rect boundRect = cv::boundingRect(cv::Mat(approx));
cv::rectangle(dst, boundRect.tl(), boundRect.br(), cv::Scalar(255, 255, 255), 3, 8, 0);
}
}
// ADDED: displaying input and results
cv::imshow("input", src);
cv::imshow("dst", dst);
cv::imwrite("C:/StackOverflow/Output/rectangles.png", dst);
cv::waitKey(0);
return 0;
}
使用你的输入图像我得到了这个输出:
这可能不是您所期望的。查看精明的输出图像(查看中间结果以进行可视化调试总是好的!),图像中的结构太多,轮廓将覆盖所有这些,因此有些结构将近似为多项式有 4 到 6 个元素。
相反,您必须变得更聪明一些。您可以尝试使用 cv::HoughLinesP 提取直线并连接这些线。或者您可以尝试先通过查找白色区域来分割图像(如果您的矩形始终为白色)。
int main(int argc, char* argv[])
{
cv::Mat src = cv::imread("C:/StackOverflow/Input/rectangles.png");
cv::Mat dst = src.clone();
cv::Mat gray;
cv::cvtColor(src, gray, CV_BGR2GRAY);
cv::Mat mask;
// find "white" pixel
cv::inRange(src, cv::Scalar(230, 230, 230), cv::Scalar(255, 255, 255), mask);
cv::imshow("mask", mask);
std::vector<std::vector<cv::Point> > contours;
cv::findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> approx;
for (int i = 0; i < contours.size(); i++){
cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.02, true);
if (approx.size() >= 4 && approx.size() <= 6)
{
cv::Rect boundRect = cv::boundingRect(cv::Mat(approx));
cv::rectangle(dst, boundRect.tl(), boundRect.br(), cv::Scalar(255, 255, 255), 1, 8, 0);
}
}
cv::imshow("input", src);
cv::imshow("dst", dst);
cv::imwrite("C:/StackOverflow/Output/rectangles2.png", dst);
cv::waitKey(0);
return 0;
}
给出这个结果:
如您所见,白色附近还有其他明亮区域。多项式近似也没有多大帮助。
关于c++ - 使用 OpenCV 检测绘制在背景图像上的矩形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35334088/