OpenCV——画像のコントラスト、明るさ、彩度を調整する
44129 ワード
一、画像のコントラストと明るさの調整
1、原理: である.
2、C++OpenCVコアコード:
元のピクチャの各画素を巡回し,R,G,Bをそれぞれ式で変換する.
二、画像の彩度調整
ネット上では画像の飽和度調整に関するアルゴリズムが多く、どちらを選ぶか分かりません.だから、どの効果がいいか試してみましょう.ここで、参考にしました.https://blog.csdn.net/u012198575/article/details/82985482この文章が言及したアルゴリズムは,アルゴリズムの構想がはっきりしている.
1、Photoshop飽和度調整思想(PSかどうか私にもわかりません~):は、RGBに関する各画素点の最大値、最小値を算出する. deltaを2値の差/255とし、valueを2値の和/255とする. の2値の差deltaは0で動作しない、すなわち、この画素点をスキップする.そうでなければ、次の操作を行います: RGB画像をHSL画像(Hue:色彩,Saturability:飽和度,Light:輝度) に変換する. light=value/2、light<0.5の場合sat=delta/value;そうでない場合:sat=delta/(2-value); 最後に、インクリメンタル判定によりどのような処理を行うかを判断し、変換後の新たなRGB値を新たなピクチャに格納する.
2、C++コアコード:
三、OpenCV実現の画像のコントラスト、明るさ、飽和度の完全なコード
1、原理:
f(row, col)
:オリジナル画像の画素.g(row, col)
:調整後の画像の画素.a(a>0
:利得(gain)と呼ばれ、画像のコントラストを制御するためによく用いられるが、その値範囲は一般的に0.0-3.0 b
:バイアス(bias)と呼ばれ、画像の輝度を制御するためによく用いられる.g(row, col) = a*f(row, col) + b
:元の画像に従ってコントラスト輝度を調整する式.new_img.at (row, col)[c]
:opencvは、ピクチャの各画素の構文にアクセスする.saturate_cast()
:オーバーフロー防止.演算が完了すると、結果は負になり、0に変わり、結果は255を超え、255になります.2、C++OpenCVコアコード:
元のピクチャの各画素を巡回し,R,G,Bをそれぞれ式で変換する.
void contrast_bright (int, void*)
{
contrastValue_f = 0.1 * contrastValue; // , contrastValue 。
for (int row = 0; row < img.rows; row++)
{
for (int col = 0; col < img.cols; col++)
{
for (int c = 0; c < 3; c++) {
new_img.at<Vec3b> (row, col)[c] = saturate_cast<uchar>(contrastValue_f * (img.at<Vec3b> (row, col)[c]) + brightValue); // g(x,y) = af(x,y) + b; a ,b
}
}
}
imshow ("Effect Image", new_img);
}
Mat.at (row, col)[c]
:ピクチャ画素を巡回する方法.https://docs.opencv.org/3.4/d5/d98/tutorial_mat_operations.html saturate_cast
:オーバーフロー防止.二、画像の彩度調整
ネット上では画像の飽和度調整に関するアルゴリズムが多く、どちらを選ぶか分かりません.だから、どの効果がいいか試してみましょう.ここで、参考にしました.https://blog.csdn.net/u012198575/article/details/82985482この文章が言及したアルゴリズムは,アルゴリズムの構想がはっきりしている.
1、Photoshop飽和度調整思想(PSかどうか私にもわかりません~):
2、C++コアコード:
void saturability (int, void*)
{
float increment = (saturation - 80) * 1.0 / max_increment;
for (int col = 0; col < img.cols; col++)
{
for (int row = 0; row < img.rows; row++)
{
// R,G,B 2,1,0
uchar r = img.at<Vec3b> (row, col)[2];
uchar g = img.at<Vec3b> (row, col)[1];
uchar b = img.at<Vec3b> (row, col)[0];
float maxn = max (r, max (g, b));
float minn = min (r, min (g, b));
float delta, value;
delta = (maxn - minn) / 255;
value = (maxn + minn) / 255;
float new_r, new_g, new_b;
if (delta == 0) // 0 ,
{
new_img.at<Vec3b> (row, col)[0] = new_b;
new_img.at<Vec3b> (row, col)[1] = new_g;
new_img.at<Vec3b> (row, col)[2] = new_r;
continue;
}
float light, sat, alpha;
light = value / 2;
if (light < 0.5)
sat = delta / value;
else
sat = delta / (2 - value);
if (increment >= 0)
{
if ((increment + sat) >= 1)
alpha = sat;
else
{
alpha = 1 - increment;
}
alpha = 1 / alpha - 1;
new_r = r + (r - light * 255) * alpha;
new_g = g + (g - light * 255) * alpha;
new_b = b + (b - light * 255) * alpha;
}
else
{
alpha = increment;
new_r = light * 255 + (r - light * 255) * (1 + alpha);
new_g = light * 255 + (g - light * 255) * (1 + alpha);
new_b = light * 255 + (b - light * 255) * (1 + alpha);
}
new_img.at<Vec3b> (row, col)[0] = new_b;
new_img.at<Vec3b> (row, col)[1] = new_g;
new_img.at<Vec3b> (row, col)[2] = new_r;
}
}
imshow ("Effect Image", new_img);
}
三、OpenCV実現の画像のコントラスト、明るさ、飽和度の完全なコード
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
int contrastValue; //
float contrastValue_f; // , contrastValue
int brightValue; //
int saturation; //
const int max_increment = 200;
Mat img, new_img; //img: ; new_img: ;
void contrast_bright (int, void*);
void saturability (int, void*);
//
void contrast_bright (int, void*)
{
contrastValue_f = 0.1 * contrastValue;
for (int row = 0; row < img.rows; row++)
{
for (int col = 0; col < img.cols; col++)
{
for (int c = 0; c < 3; c++) {
new_img.at<Vec3b> (row, col)[c] = saturate_cast<uchar>(contrastValue_f * (img.at<Vec3b> (row, col)[c]) + brightValue); // g(x,y) = af(x,y) + b; a ,b
}
}
}
imshow ("Effect Image", new_img);
}
//
void saturability (int, void*)
{
float increment = (saturation - 80) * 1.0 / max_increment;
for (int col = 0; col < img.cols; col++)
{
for (int row = 0; row < img.rows; row++)
{
// R,G,B 2,1,0
uchar r = img.at<Vec3b> (row, col)[2];
uchar g = img.at<Vec3b> (row, col)[1];
uchar b = img.at<Vec3b> (row, col)[0];
float maxn = max (r, max (g, b));
float minn = min (r, min (g, b));
float delta, value;
delta = (maxn - minn) / 255;
value = (maxn + minn) / 255;
float new_r, new_g, new_b;
if (delta == 0) // 0 ,
{
new_img.at<Vec3b> (row, col)[0] = new_b;
new_img.at<Vec3b> (row, col)[1] = new_g;
new_img.at<Vec3b> (row, col)[2] = new_r;
continue;
}
float light, sat, alpha;
light = value / 2;
if (light < 0.5)
sat = delta / value;
else
sat = delta / (2 - value);
if (increment >= 0)
{
if ((increment + sat) >= 1)
alpha = sat;
else
{
alpha = 1 - increment;
}
alpha = 1 / alpha - 1;
new_r = r + (r - light * 255) * alpha;
new_g = g + (g - light * 255) * alpha;
new_b = b + (b - light * 255) * alpha;
}
else
{
alpha = increment;
new_r = light * 255 + (r - light * 255) * (1 + alpha);
new_g = light * 255 + (g - light * 255) * (1 + alpha);
new_b = light * 255 + (b - light * 255) * (1 + alpha);
}
new_img.at<Vec3b> (row, col)[0] = new_b;
new_img.at<Vec3b> (row, col)[1] = new_g;
new_img.at<Vec3b> (row, col)[2] = new_r;
}
}
imshow ("Effect Image", new_img);
}
int main ()
{
img = imread ("test.jpg"); // , Mat img
new_img = Mat::zeros (img.size (), img.type ()); //
contrastValue = 1; //
brightValue = 1; //
saturation = 10; //
namedWindow ("Effect Image", WINDOW_NORMAL); //
createTrackbar ("Contrast:", "Effect Image", &contrastValue, 100, contrast_bright); //
createTrackbar ("Brightness:", "Effect Image", &brightValue, 200, contrast_bright); //
createTrackbar ("Saturability:", "Effect Image", &saturation, 200, saturability); //
// , , userdata 0
contrast_bright (contrastValue, 0);
contrast_bright (brightValue, 0);
saturability (saturation, 0);
cv::waitKey (0);
return 0;
}