Ash*_*hok 7 c++ opencv average real-time contour
我的图像有大约50到100个小轮廓.我希望实时找到每个轮廓的平均强度[1] [2].我能想到的一些方法是
为每个轮廓绘制带有FILLED选项的轮廓; 使用每个图像作为原始图像上的掩模,从而找到平均值.但我认为这种方法乍一看不是实时的.
drawContour使用FILLED选项研究OpenCV 函数的实现,并以相同的方式访问轮廓包围的像素.但代码看起来非常复杂,不容易理解.
计算最小面积矩形,使用变换找到矩形内的所有点,并找到非零点的平均值.再次,似乎是复杂的方法.
有没有更简单有效的方法来做到这一点?
[1]每个非重叠轮廓所包围的所有像素强度的平均值
[2]在2.66 Ghz台式PC上每秒约25,(960 x 480)像素图像
Aur*_*ius 10
我无法提出与您建议的方法大不相同的任何方法.但是,我能够做一些可能有助于指导您决定的时间安排.我的所有时间都在iMac上的1280*720图像上运行,仅限于找到100个轮廓.您的机器上的时间当然会有所不同,但相对时间应该是提供信息的.
对于每个测试用例,声明如下:
std::vector<std::vector<cv::Point>> cont; // Filled by cv::findContours()
cv::Mat labels = cv::Mat::zeros(image.size(), CV_8UC1);
std::vector<float> cont_avgs(cont.size(), 0.f); // This contains the averages of each contour
Run Code Online (Sandbox Code Playgroud)
方法1在概念上是最简单的,但它也是最慢的.通过为每个轮廓分配唯一的颜色来标记每个轮廓.通过迭代图像中的每个像素来对每个标记的分量的值求和.
for (size_t i = 0; i < cont.size(); ++i)
{
// Labels starts at 1 because 0 means no contour
cv::drawContours(labels, cont, i, cv::Scalar(i+1), CV_FILLED);
}
std::vector<float> counts(cont.size(), 0.f);
const int width = image.rows;
for (size_t i = 0; i < image.rows; ++i)
{
for (size_t j = 0; j < image.cols; ++j)
{
uchar label = labels.data[i*width + j];
if (label == 0)
{
continue; // No contour
}
else
{
label -= 1; // Make labels zero-indexed
}
uchar value = image.data[i*width + j];
cont_avgs[label] += value;
++counts[label];
}
}
for (size_t i = 0; i < cont_avgs.size(); ++i)
{
cont_avgs[i] /= counts[i];
}
Run Code Online (Sandbox Code Playgroud)
未修改的方法3具有最简单的实现,也是最快的.填充所有轮廓以用作寻找平均值的掩模.计算每个轮廓的边界矩形,然后使用边界框内的掩模计算平均值.
警告:如果任何其他轮廓位于感兴趣轮廓的边界矩形内,则此方法将给出不正确的结果.
cv::drawContours(labels, cont, -1, cv::Scalar(255), CV_FILLED);
for (size_t i = 0; i < cont.size(); ++i)
{
cv::Rect roi = cv::boundingRect(cont[i]);
cv::Scalar mean = cv::mean(image(roi), labels(roi));
cont_avgs[i] = mean[0];
}
Run Code Online (Sandbox Code Playgroud)
对方法3稍作修改会略微增加执行时间,但无论轮廓位置如何,都可以获得正确结果.每个轮廓都单独标记,并且仅使用该轮廓的掩模计算平均值.
for (size_t i = 0; i < cont.size(); ++i)
{
cv::drawContours(labels, cont, i, cv::Scalar(i), CV_FILLED);
cv::Rect roi = cv::boundingRect(cont[i]);
cv::Scalar mean = cv::mean(image(roi), labels(roi) == i);
cont_avgs[i] = mean[0];
}
Run Code Online (Sandbox Code Playgroud)