谁能帮我找出前 1%(或者说前 100 个像素)最亮的像素以及它们在 opencv 中的灰度图像位置。因为 cvMinMaxLoc() 只给出最亮的像素位置。
任何帮助是极大的赞赏。
谁能帮我找出前 1%(或者说前 100 个像素)最亮的像素以及它们在 opencv 中的灰度图像位置。因为 cvMinMaxLoc() 只给出最亮的像素位置。
任何帮助是极大的赞赏。
这是一种简单但不完善/愚蠢的方法:
for i=1:100
get brightest pixel using cvMinMaxLoc
store location
set it to a value of zero
end
如果您不介意效率,这应该可行。
您还应该检查 cvInRangeS 以找到定义低阈值和高阈值的其他类似值的像素。
您需要根据直方图计算亮度阈值。然后您遍历像素以获得足够亮以满足阈值的那些位置。下面的程序将阈值应用于图像并显示结果以用于演示目的:
#!/usr/bin/env python3
import sys
import cv2
import matplotlib.pyplot as plt
if __name__ == '__main__':
if len(sys.argv) != 2 or any(s in sys.argv for s in ['-h', '--help', '-?']):
print('usage: {} <img>'.format(sys.argv[0]))
exit()
img = cv2.imread(sys.argv[1], cv2.IMREAD_GRAYSCALE)
hi_percentage = 0.01 # we want we the hi_percentage brightest pixels
# * histogram
hist = cv2.calcHist([img], [0], None, [256], [0, 256]).flatten()
# * find brightness threshold
# here: highest thresh for including at least hi_percentage image pixels,
# maybe you want to modify it for lowest threshold with for including
# at most hi_percentage pixels
total_count = img.shape[0] * img.shape[1] # height * width
target_count = hi_percentage * total_count # bright pixels we look for
summed = 0
for i in range(255, 0, -1):
summed += int(hist[i])
if target_count <= summed:
hi_thresh = i
break
else:
hi_thresh = 0
# * apply threshold & display result for demonstration purposes:
filtered_img = cv2.threshold(img, hi_thresh, 0, cv2.THRESH_TOZERO)[1]
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.subplot(122)
plt.imshow(filtered_img, cmap='gray')
plt.axis('off')
plt.tight_layout()
plt.show()
基于发布的其他一些想法的 C++ 版本:
// filter the brightest n pixels from a grayscale img, return a new mat
cv::Mat filter_brightest( const cv::Mat& src, int n ) {
CV_Assert( src.channels() == 1 );
CV_Assert( src.type() == CV_8UC1 );
cv::Mat result={};
// simple histogram
std::vector<int> histogram(256,0);
for(int i=0; i< int(src.rows*src.cols); ++i)
histogram[src.at<uchar>(i)]++;
// find max threshold value (pixels from [0-max_threshold] will be removed)
int max_threshold = (int)histogram.size() - 1;
for ( ; max_threshold >= 0 && n > 0; --max_threshold ) {
n -= histogram[max_threshold];
}
if ( max_threshold < 0 ) // nothing to do
src.copyTo(result);
else
cv::threshold(src, result, max_threshold, 0., cv::THRESH_TOZERO);
return result;
}
用法示例:获得前 1%
auto top1 = filter_brightest( img, int((img.rows*img.cols) * .01) );
尝试改用cvThreshold。
那么最合乎逻辑的方法是迭代整个图片,然后获取像素的max
和min
值。然后选择一个阈值,它将为您提供所需的百分比(在您的情况下为 1%)。之后再次迭代并保存高于给定阈值的每个像素的i
和j
坐标。这样,您将只迭代矩阵两次而不是 100 次(或 1% 的像素次)并选择最亮的并删除它。
OpenCV 垫子是多维数组。灰度图像是二维数组,值从 0 到 255。您可以像这样遍历矩阵。
for(int i=0;i < mat.height();i++)
for(int j=0;j < mat.width();j++)
mat[i][j];