OpenCV中没有内置的解决方案来执行直方图拉伸,但是您可以在循环中轻松实现它。
imadjust
允许选择上限和下限的容差,或直接选择边界,因此您需要比简单的for循环更多的逻辑。
您可以使用下面的示例作为参考来实现自己的直方图拉伸:
#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
void imadjust(const Mat1b& src, Mat1b& dst, int tol = 1, Vec2i in = Vec2i(0, 255), Vec2i out = Vec2i(0, 255))
{
dst = src.clone();
tol = max(0, min(100, tol));
if (tol > 0)
{
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)]++;
}
}
vector<int> cum = hist;
for (int i = 1; i < hist.size(); ++i) {
cum[i] = cum[i - 1] + hist[i];
}
int total = src.rows * src.cols;
int low_bound = total * tol / 100;
int upp_bound = total * (100-tol) / 100;
in[0] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), low_bound));
in[1] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), upp_bound));
}
float scale = float(out[1] - out[0]) / float(in[1] - in[0]);
for (int r = 0; r < dst.rows; ++r)
{
for (int c = 0; c < dst.cols; ++c)
{
int vs = max(src(r, c) - in[0], 0);
int vd = min(int(vs * scale + 0.5f) + out[0], out[1]);
dst(r, c) = saturate_cast<uchar>(vd);
}
}
}
int main()
{
Mat3b img = imread("path_to_image");
Mat1b gray;
cvtColor(img, gray, COLOR_RGB2GRAY);
Mat1b adjusted;
imadjust(gray, adjusted);
return 0;
}
输入图像:
![进入图片描述](https://istack.dev59.com/Xm5oD.webp)
输出调整后的图像:
![进入图片描述](https://istack.dev59.com/cH8B0.webp)
cv::xphoto::SimpleWB
类,它执行类似于imadjust
的直方图拉伸。以下是实现代码:https://github.com/opencv/opencv_contrib/blob/3.2.0/modules/xphoto/src/simple_color_balance.cpp - Amro