Bias/Gain 是非線性色調映射函數,常用於影像合成與色調調整。輸入輸出均為 [0,1] 正規化像素值。
b > 0.5 提亮中間調,b < 0.5 壓暗中間調。g > 0.5 增加對比度(S 形曲線),g < 0.5 降低對比度(反 S 形)。標準定義(Perlin 1985):
Bias(b, x) = x / ( (1/b - 2)*(1 - 2x) + 1 )
Gain(g, x) = x < 0.5 ? Bias(2x, g)/2 : 1 - Bias(2(1-x), g)/2
組合應用:out = Bias( Gain(x, gain), bias )。
#include <opencv2/opencv.hpp>
#include <cmath>
using namespace cv;
using namespace std;
float Bias(float x, float b) {
if (b <= 0.0f) return 0.0f;
if (b >= 1.0f) return 1.0f;
if (x <= 0.0f) return 0.0f;
if (x >= 1.0f) return 1.0f;
float c = (1.0f/b - 2.0f) * (1.0f - 2.0f*x);
return (x < 0.5f) ? x / (c + 1.0f) : (c - x) / (c - 1.0f);
}
float Gain(float x, float g) {
if (g <= 0.0f) return 0.0f;
if (g >= 1.0f) return 1.0f;
if (x <= 0.0f) return 0.0f;
if (x >= 1.0f) return 1.0f;
float p = log(1.0f - g) / log(0.5f);
if (x < 0.5f) return 0.5f * pow(2.0f * x, p);
else return 1.0f - 0.5f * pow(2.0f * (1.0f - x), p);
}
void showImage(const Mat& img, const string& name) {
namedWindow(name, WINDOW_AUTOSIZE);
imshow(name, img);
}
int main() {
Mat src = imread("4.jpg");
if (src.empty()) return -1;
Mat dst(src.size(), CV_32FC3); // 浮點運算用 32F
float gain_val = 0.75f;
float bias_val = 0.25f;
for (int y = 0; y < src.rows; ++y) {
for (int x = 0; x < src.cols; ++x) {
for (int k = 0; k < 3; ++k) {
float val = src.at<Vec3b>(y, x)[k] / 255.0f; // 正規化
val = Gain(val, gain_val);
val = Bias(val, bias_val);
dst.at<Vec3f>(y, x)[k] = val;
}
}
}
// 顯示需轉回 8U 或直接用 imshow 支援 32F (0~1)
showImage(dst, "Bias_Gain");
waitKey(0);
return 0;
}
| 參數 | 值域 | < 0.5 效果 | > 0.5 效果 |
|---|---|---|---|
| Bias | [0,1] | 壓暗中間調(向陰影偏移) | 提亮中間調(向高光偏移) |
| Gain | [0,1] | 降低對比度(灰階壓縮) | 增加對比度(灰階拉伸) |