[英]How to count all non-zero pixels within each polygon area efficiently?
I want to calculate numbers of all white pixels within every polygon area efficiently.我想有效地计算每个多边形区域内所有白色像素的数量。
Given some processes:鉴于一些过程:
// 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);
So until now, we can get a image with multiple polygon areas(say we have 3 areas) which have white( with value 255) pixels.所以到目前为止,我们可以得到一个具有多个多边形区域(假设我们有 3 个区域)的图像,这些区域具有白色(值为 255)像素。 Then after some operations we expect to get a vector like:
然后经过一些操作,我们希望得到一个向量,如:
// some efficient operations
// ...
vector<int> pixelNums;
The size of pixelNums should be same with polygons which is 3 here. pixelNums 的大小应与多边形相同,此处为 3。 And if we print them we may get some outputs like(the values are basically depended on the pre-processes):
如果我们打印它们,我们可能会得到一些输出(这些值基本上取决于预处理):
index: 0; value: 120
index: 1; value: 1389
index: 2; value: 0
Here is my thought.这是我的想法。 Counting every pixels within every polygon area with help of
cv::countNonZero
, but I need to call it within a loop which I don't think it's a efficient way, isn't it?在
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));
}
If you have some better ways, please kindly answer this post.如果您有更好的方法,请回复此帖子。 Here I say
better way
is consuming as little time as you can just in cpu environment.在这里我说
better way
是在 cpu 环境中消耗尽可能少的时间。
There are some minor improvements that can be done, but all of them combined should provide a decent speedup.有一些小的改进可以做,但所有这些结合起来应该可以提供不错的加速。
const auto&
const auto&
Example code:示例代码:
#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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.