我想有效地计算每个多边形区域内所有白色像素的数量。
给出一些过程:
// some codes for reading gray image
// cv::Mat gray = cv::imread("gray.jpg");
// given polygons
// vector< vector<cv::Point> > polygons;
cv::Mat cropped;
cv::Mat mask = cv::Mat::zeros(gray.size(), CV_8UC1);
cv::fillPoly(mask, polygons, cv::Scalar(255));
cv::bitwise_and(gray, gray, cropped, mask);
cv::Mat binary;
cv::threshold(cropped, binary, 20, 255, CV_THRESH_BINARY);
因此,到目前为止,我们可以获得具有多个多边形区域(例如,我们有3个区域)的图像,这些区域具有白色(值为255)像素。然后,经过一些操作,我们期望得到一个像这样的向量:
// some efficient operations
// ...
vector<int> pixelNums;
pixelNums的大小应与此处为3的多边形相同。如果我们将它们打印出来,我们可能会得到一些输出(值基本上取决于预处理):
index: 0; value: 120
index: 1; value: 1389
index: 2; value: 0
这是我的想法。在cv::countNonZero
的帮助下对每个多边形区域中的每个像素进行计数,但是我需要在一个循环中调用它,我认为这不是一种有效的方法,不是吗?
vector<int> pixelNums;
for(auto polygon : polygons)
{
vector< vector<cv::Point> > temp_polygons;
temp_polygons.push_back(polygon);
cv::Mat cropped;
cv::Mat mask = cv::Mat::zeros(gray.size(), CV_8UC1);
cv::fillPoly(mask, temp_polygons, cv::Scalar(255));
cv::bitwise_and(gray, gray, cropped, mask);
cv::Mat binary;
cv::threshold(cropped, binary, 20, 255, CV_THRESH_BINARY);
pixelNums.push_back(cv::countNonZero(binary));
}
如果您有更好的方法,请回答此帖子。在这里,我说better way
仅在CPU环境中消耗的时间最少。
答案 0 :(得分:1)
可以做一些小的改进,但是所有这些结合起来应该可以提供不错的加速效果。
const auto&
示例代码:
#include <vector>
#include <opencv2/opencv.hpp>
int main()
{
// Your image
cv::Mat1b gray = cv::imread("path/to/image", cv::IMREAD_GRAYSCALE);
// Your polygons
std::vector<std::vector<cv::Point>> polygons
{
{ {15,120}, {45,200}, {160,160}, {140, 60} },
{ {10,10}, {15,30}, {50,25}, {40, 15} },
// etc...
};
// Compute the threshold just once
cv::Mat1b thresholded = gray > 20;
std::vector<int> pixelNums;
for (const auto& polygon : polygons)
{
// Get bbox of polygon
cv::Rect bbox = cv::boundingRect(polygon);
// Make a new (small) mask
cv::Mat1b mask(bbox.height, bbox.width, uchar(0));
cv::fillPoly(mask, std::vector<std::vector<cv::Point>>{polygon}, cv::Scalar(255), 8, 0, -bbox.tl());
// Get crop
cv::Mat1b cropped = thresholded(bbox) & mask;
// Compute the number of white pixels only on the crop
pixelNums.push_back(cv::countNonZero(cropped));
}
return 0;
}