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ところで:輪郭を1つだけ描きたい場合、新しい配列(3行目と4行目)の作成を避ける方法はありますか?

4

1 に答える 1

3

エラーは、drawContours のオフセットの代数記号にあると思います。次の出力を生成するこのサンプル コードの意味をお見せしましょう。using-mask-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 に答える