假设我在OpenCV中有一个灰度图像。
我想找一个值,以便图片中5%
像素的值大于它。
我可以迭代像素并查找具有相同值的像素数,然后从结果中找到像素的%5高于我的值的值,但我正在寻找更快的方法来执行此操作。 OpenCV中有没有这样的技术?
我认为直方图会有所帮助,但我不确定如何使用它。
答案 0 :(得分:2)
你需要:
如果生成的图像均匀随机,则会得到如下的直方图:
和累积直方图一样(你需要找到其值超过蓝线的第一个bin):
然后你需要找到合适的垃圾箱。您可以使用std::lower_bound函数查找正确的值,并使用std::distance查找相应的bin编号(也就是您要查找的值)。 (请注意,使用lower_bound
,您将找到值为greater or equal
的元素到给定值。您可以使用upper_bound来查找值严格的元素更大然后是给定值)
在这种情况下,结果为242
,从0到255的均匀分布是有意义的,因为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;
}
注意强>
答案 1 :(得分:0)
1)确定图像的高度和宽度h
和w
。
2)确定像素总数的5%是(X)...
X = int(h * w * 0.05)
3)从直方图中最亮的bin开始。设置总计T
= 0。
4)将此bin中的像素数添加到总T
。如果T
大于X
,则表示您已完成,所需的值是当前直方图区间范围的下限。
3)移动直方图中的下一个较暗的bin。转到4。