【发布时间】:2016-02-23 03:34:29
【问题描述】:
假设我在 OpenCV 中有一个灰度图像。
我想找到一个值,使图像中5% 像素的值大于它。
我可以遍历像素并找到具有相同值的像素数,然后从结果中找到像素的 %5 高于我的值的值,但我正在寻找一种更快的方法来做到这一点。 OpenCV中有没有这样的技术?
我认为直方图会有所帮助,但我不确定如何使用它。
【问题讨论】:
标签: c++ opencv image-processing opencv3.0
假设我在 OpenCV 中有一个灰度图像。
我想找到一个值,使图像中5% 像素的值大于它。
我可以遍历像素并找到具有相同值的像素数,然后从结果中找到像素的 %5 高于我的值的值,但我正在寻找一种更快的方法来做到这一点。 OpenCV中有没有这样的技术?
我认为直方图会有所帮助,但我不确定如何使用它。
【问题讨论】:
标签: c++ opencv image-processing opencv3.0
你需要:
给定一个均匀随机生成的图像,您会得到如下直方图:
和累积直方图一样(你需要找到第一个值超过蓝线的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) 确定图片的高度和宽度,h 和w。
2) 确定总像素数的5%是多少(X)...
X = int(h * w * 0.05)
3) 从直方图中最亮的 bin 开始。设置总计T = 0。
4) 将此 bin 中的像素数添加到您的总数 T。如果T 大于X,你就完成了,你想要的值是当前直方图 bin 范围的下限。
3) 移动到直方图中下一个较暗的 bin。转到 4。
【讨论】: