图像处理——灰度变换
1 灰度变换简介
灰度变换是对图像的每个像素按照灰度映射函数进行映射的变换,其作用于每个像素。灰度变换一般用来进行图像增强,提高图像的对比度,改善图像的灰度分布等。灰度变换根据灰度变换函数的不同分为线性函数变换、对数函数和幂函数变换。 $$ pout_{i,j}=f(pin_{i,j}) $$
$f$为灰度变换函数,$i$和$j$分别为图像的下标索引,$pin_{ij}$为$i,j$处像素值。
灰度变换的函数可以使任意函数,可以根据不同的使用场景选择不同的灰度变换函数。

最简单的灰度变换的实现如下,遍历每一个像素然后使用函数Func来处理每个像素
template<class Func>
static Mat pixelWiseTransform(const Mat &img, Func f) {
Mat retMat = img.clone();
for (int i = 0; i < img.rows; i++) {
for (int j = 0; j < img.cols; j++) {
for (int k = 0; k < img.channels(); k++) {
if (img.channels() == 3) {
retMat.at<cv::Vec3b>(i, j)[k] = static_cast<uchar>(imgValueLmit(f(retMat.at<cv::Vec3b>(i, j)[k])));
}
else if (img.channels() == 1) {
retMat.at<uchar>(i, j) = static_cast<uchar>(imgValueLmit(f(retMat.at<uchar>(i, j))));
}
else {
abort();
}
}
}
}
return std::move(retMat);
}
2 线性灰度变换
最简单的灰度变换函数就是线性灰度变换,线性灰度变换的灰度变换函数为线性函数: $$ f(x)=ax+b $$ $a$为斜率,$b$为$y$轴截距,$x$为输入点的像素值,$f(x)$为对应点的输出像素值。
$a = 1, b = 0$时,为恒定函数,图像不会发生变化;
$a = -1, b = 255$时,图像发生反转;

$a = 1, b != 0$时,图像中的值整体增大b,图像整体变暗或者变亮;

$a < 0, b恒定$时;

$a > 1, b恒定$时,图像对比度增加,整体变亮亮的更亮,黑的变灰色;
$a < 1 \And a > 0, b恒定$时,图像对比度减小,整体变暗;

3 对数变换
对数变换的通用形式为:
$$
pout_{i,j}=clog(p1 + pin_{i,j})
$$
对数变换,将源图像中范围较窄的低灰度值映射到范围较宽的灰度区间,同时将范围较宽的高灰度值区间映射为较窄的灰度区间,从而扩展了暗像素的值,压缩了高灰度的值,能够对图像中低灰度细节进行增强。

4 幂变换
幂变换的基本形式为 $$ pout_{i,j}=c{pin_{i,j}}^{r} $$ 伽马变换的效果与对数变换有点类似,当$γ>1$时将较窄范围的低灰度值映射为较宽范围的灰度值,同时将较宽范围的高灰度值映射为较窄范围的灰度值;当$γ<1$时,情况相反,与反对数变换类似。
$r为1.4$变换$c$:

$c=1$变换$r$:

gamma变换最常用的是用来校正显示器显示颜色的亮度。
5 分段函数变换
分段函数变换可以根据具体的需要设计多段映射函数来处理不同灰度段的颜色,每段的映射可以是线性映射也可以非线性映射。
