如何找到与特定像素数相对应的像素值? [英] How to find the pixel value that corresponds to a specific number of pixels?
问题描述
假设我在OpenCV中有一个灰度图像.
Assume that I have a grayscale image in OpenCV.
我想找到一个值,以使图像中像素的5%
值大于该值.
I want to find a value so that 5%
of pixels in the images have a value greater than it.
我可以遍历像素并找到具有相同值的像素数量,然后从结果中找到像素%5高于我的值的值,但是我正在寻找一种更快的方法. OpenCV中有这种技术吗?
I can iterate over pixels and find number of pixels with the same value and then from the result find the value that %5 of pixel are above my value, but I am looking for a faster way to do this. Is there any such technique in OpenCV?
我认为直方图会有所帮助,但是我不确定如何使用它.
I think histogram would help, but I am not sure how I can use it.
推荐答案
您需要:
- 计算像素值的累积直方图
- 查找值大于像素总数的95%(100-5)的bin.
鉴于均匀随机生成的图像,您将得到如下直方图:
Given an image uniformly random generated, you get an histogram like:
和类似的累积直方图(您需要找到第一个bin的值在蓝线上):
and the cumulative histogram like (you need to find the first bin whose value is over the blue line):
然后,您需要找到正确的纸槽.您可以使用 std :: lower_bound 函数找到正确的值,然后 std :: distance 来找到相应的bin号(也就是您想要的值)找). (请注意,使用lower_bound
时,您会发现其值是greater or equal
到给定值的元素.您可以使用
Then you need to find the proper bin. You can use std::lower_bound function to find the correct value, and std::distance to find the corresponding bin number (aka the value you want to find). (Please note that with lower_bound
you'll find the element whose value is greater or equal
to the given value. You can use upper_bound to find the element whose value is strictly greater then the given value)
在这种情况下,结果为242
,从255*0.95 = 242.25
开始,这对于从0到255的均匀分布是有意义的.
In this case it results to be 242
, which make sense for an uniform distribution from 0 to 255, since 255*0.95 = 242.25
.
检查完整代码:
#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
void drawHist(const vector<int>& data, Mat3b& dst, int binSize = 3, int height = 0, int ref_value = -1)
{
int max_value = *max_element(data.begin(), data.end());
int rows = 0;
int cols = 0;
float scale = 1;
if (height == 0) {
rows = max_value + 10;
}
else {
rows = height;
scale = float(height) / (max_value + 10);
}
cols = data.size() * binSize;
dst = Mat3b(rows, cols, Vec3b(0, 0, 0));
for (int i = 0; i < data.size(); ++i)
{
int h = rows - int(scale * data[i]);
rectangle(dst, Point(i*binSize, h), Point((i + 1)*binSize - 1, rows), (i % 2) ? Scalar(0, 100, 255) : Scalar(0, 0, 255), CV_FILLED);
}
if (ref_value >= 0)
{
int h = rows - int(scale * ref_value);
line(dst, Point(0, h), Point(cols, h), Scalar(255,0,0));
}
}
int main()
{
Mat1b src(100, 100);
randu(src, Scalar(0), Scalar(255));
int percent = 5; // percent % of pixel values are above a val
int val; // I need to find this value
int n = src.rows * src.cols; // Total number of pixels
int th = cvRound((100 - percent) / 100.f * n); // Number of pixels below val
// Histogram
vector<int> hist(256, 0);
for (int r = 0; r < src.rows; ++r) {
for (int c = 0; c < src.cols; ++c) {
hist[src(r, c)]++;
}
}
// Cumulative histogram
vector<int> cum = hist;
for (int i = 1; i < hist.size(); ++i) {
cum[i] = cum[i - 1] + hist[i];
}
// lower_bound returns an iterator pointing to the first element
// that is not less than (i.e. greater or equal to) th.
val = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), th));
// Plot histograms
Mat3b plotHist, plotCum;
drawHist(hist, plotHist, 3, 300);
drawHist(cum, plotCum, 3, 300, *lower_bound(cum.begin(), cum.end(), th));
cout << "Value: " << val;
imshow("Hist", plotHist);
imshow("Cum", plotCum);
waitKey();
return 0;
}
注意
- The histogram drawing function is an upgrade from a former version I posted here
- You can use calcHist to compute the histograms, but I personally find easier to use the aforementioned method for 1D histograms.
这篇关于如何找到与特定像素数相对应的像素值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!