2

问题
我想计算属于轮廓的像素值的平均值,该轮廓作为 OpenCV 中的点向量给出。与轮廓相比,图像相当大,所以我想先设置一个与轮廓边界框一样大的 ROI,然后再进行遮罩。但是,这并没有真正起作用,我得到零作为平均值计算的结果。

带有行号的代码

1)  Mat crop = Mat(*img, bounding_box); //img is the original image (may be 1024*1024)  
2)  Mat mask = Mat::zeros(crop.rows, crop.cols, CV_8UC1); //the mask with the size of cropped image  
3)  vector<vector<Point> > contours;  
4)  contours.push_back(*cv_contour);   
5)  drawContours(mask, contours, -1, Scalar(255), CV_FILLED, CV_AA, noArray(), 1, bounding_box.tl());   
6)  double mean_ = sum(mean(crop, mask))[0]; // returns wrong results (0)

drawContours顺便说一句:如果我只想绘制一个轮廓,有没有办法避免创建新数组(第 3 行和第 4 行) ?

4

1 回答 1

3

我猜你的错误是在drawContours的偏移量中的代数符号。让我告诉你,我对产生以下输出的示例代码的意思是:http: //daiw.de/share/Forum/stackoverflow_calculating-image-pixel-values-eg-the-mean-of-contour-inliers-使用掩码-r_001.png

#include <opencv2/opencv.hpp>
#include <iostream>
#include <algorithm>
#include <iterator>

int main()
{
    // Create a small image with a circle in it.
    cv::Mat image(256, 256, CV_8UC3, cv::Scalar(0, 0, 0));
    cv::circle(image, cv::Point(80, 110), 42, cv::Scalar(255, 127, 63), -1);

    // Create random Contour
    typedef cv::vector<cv::Point> TContour;
    TContour contour;
    contour.push_back(cv::Point(20, 30));
    contour.push_back(cv::Point(40, 110));
    contour.push_back(cv::Point(140, 140));
    contour.push_back(cv::Point(160, 50));

    // The conversion to cv::vector<cv::vector<cv::Point>> is unavoidable,
    // but can easily be achieved with a temporary instance.
    cv::Mat imageWithContour(image.clone());
    typedef cv::vector<TContour> TContours;
    cv::drawContours(imageWithContour, TContours(1, contour), -1, cv::Scalar(255, 255, 255));

    // Show the contour.
    cv::imshow("image with contour", imageWithContour);

    // Get ROI image.
    cv::Rect roi(cv::boundingRect(contour));
    cv::Mat crop(image, roi);

    // Calculate ROI mean.
    cv::Mat mask(cv::Mat::zeros(crop.rows, crop.cols, CV_8UC1)); //the mask with the size of cropped image
    // The offset for drawContours has to be *minus* roi.tl();
    cv::drawContours(mask, TContours(1, contour), -1, cv::Scalar(255), CV_FILLED, CV_AA, cv::noArray(), 1, -roi.tl());
    //auto mean(cv::sum(cv::mean(crop, mask)));
    auto mean(cv::mean(crop, mask));
    auto sum(cv::sum(mean));

    // Show crop and mask.
    cv::imshow("crop", crop);
    cv::imshow("mask", mask);

    // Print mean.
    std::cout << "mean: " << mean[0] << ", " << mean[1] << ", " << mean[2] << std::endl;
    std::cout << "sum: " << sum[0] << std::endl;

    // Wait for user input.
    cv::waitKey();
}

通常,在处理图像时,仅直观地查看中间步骤是一个好主意。

于 2012-12-05T14:27:28.250 回答