【发布时间】:2014-03-11 15:21:30
【问题描述】:
我正在使用 16 位/示例图像。
是否有(简单)方法来执行此类图像的直方图均衡(不能转换为 8bps)?
【问题讨论】:
标签: c++ opencv image-processing histogram
我正在使用 16 位/示例图像。
是否有(简单)方法来执行此类图像的直方图均衡(不能转换为 8bps)?
【问题讨论】:
标签: c++ opencv image-processing histogram
OpenCV 中的equalizeHist 只需要 8 位数据。
但 OpenCV 中的图像归一化不限于 8 位数据。请参阅它的描述here。在您的情况下,对函数的调用应如下所示:
normalize(src_image, dst_image, 0, 65535, NORM_MINMAX);
如果你想提高图像的对比度,首先尝试标准化,只有当这不起作用时才尝试均衡。标准化速度更快,破坏性更小。
参考:http://answers.opencv.org/question/3176/improve-contrast-of-a-16u-image/
【讨论】:
截至目前,OpenCV equalizeHist 仅支持 8 位图像。我基于 OpenCV 实现 here 创建了 16 位直方图均衡函数 here。
void equalizeHist16Bit(const cv::Mat &_src, cv::Mat &_dst)
{
_dst = _src.clone();
const int hist_sz = 65536;
int *hist = new int[hist_sz] {};
int *lut = new int[hist_sz] {};
for (int y = 0; y < _src.rows; y++)
for (int x = 0; x < _src.cols; x++)
hist[(int)_src.at<unsigned short int>(y, x)]++;
auto i = 0;
while (!hist[i]) ++i;
auto total = (int)_src.total();
if (hist[i] == total)
{
_dst.setTo(i);
return;
}
float scale = (hist_sz - 1.f) / (total - hist[i]);
auto sum = 0;
for (lut[i++] = 0; i < hist_sz; ++i)
{
sum += hist[i];
lut[i] = cv::saturate_cast<ushort>(sum * scale);
}
for (int y = 0; y < _src.rows; y++)
for (int x = 0; x < _src.cols; x++)
{
_dst.at<unsigned short int>(y, x) = lut[(int)_src.at<unsigned short int>(y, x)];
}
}
【讨论】:
#Simple implementation in python
#Reference: https://github.com/torywalker/histogram-equalizer/blob/master/HistogramEqualization.ipynb
import cv2
import numpy as np
import matplotlib.pyplot as plt
img_tif=cv2.imread("scan.tif",cv2.IMREAD_ANYDEPTH)
img = np.asarray(img_tif)
flat = img.flatten()
hist = get_histogram(flat,65536)
#plt.plot(hist)
cs = cumsum(hist)
# re-normalize cumsum values to be between 0-255
# numerator & denomenator
nj = (cs - cs.min()) * 65535
N = cs.max() - cs.min()
# re-normalize the cdf
cs = nj / N
cs = cs.astype('uint16')
img_new = cs[flat]
#plt.hist(img_new, bins=65536)
#plt.show(block=True)
img_new = np.reshape(img_new, img.shape)
cv2.imwrite("contrast.tif",img_new)
【讨论】:
Python 中的简单实现
参考:https://github.com/torywalker/histogram-equalizer/blob/master/HistogramEqualization.ipynb
import cv2
import numpy as np
import matplotlib.pyplot as plt
img_tif=cv2.imread("scan_before threthold_873.tif",cv2.IMREAD_ANYDEPTH)
img = np.asarray(img_tif)
flat = img.flatten()
hist = get_histogram(flat,65536)
#plt.plot(hist)
#
cs = cumsum(hist)
# re-normalize cumsum values to be between 0-255
# numerator & denomenator
nj = (cs - cs.min()) * 65535
N = cs.max() - cs.min()
# re-normalize the cdf
cs = nj / N
cs = cs.astype('uint16')
img_new = cs[flat]
#plt.hist(img_new, bins=65536)
#plt.show(block=True)
img_new = np.reshape(img_new, img.shape)
cv2.imwrite("contrast.tif",img_new)
【讨论】: