[英]How to count all non-zero pixels within each polygon area efficiently?
我想有效地計算每個多邊形區域內所有白色像素的數量。
鑒於一些過程:
// 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 環境中消耗盡可能少的時間。
有一些小的改進可以做,但所有這些結合起來應該可以提供不錯的加速。
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.