編程環(huán)境:
VS + OpenCV + C++
完整代碼已經(jīng)更新至GitHub,歡迎fork~GitHub鏈接
聲明:創(chuàng)作不易,未經(jīng)授權(quán)不得復(fù)制轉(zhuǎn)載
statement:No reprinting without authorization
內(nèi)容:
對(duì)比度及亮度的基本調(diào)整原理公式為:g(i,j) = af(i,j) + b*
->g 變換后圖像
->f 變換前原圖
->a 用于控制對(duì)比度
->b 用于控制亮度
1.1:對(duì)比度調(diào)整
? ? ? ?設(shè)計(jì)一個(gè)Sigmoid函數(shù),實(shí)現(xiàn)對(duì)圖像的對(duì)比度調(diào)整;使用opencv窗口系統(tǒng)的slider控件,交互改變Sigmoid函數(shù)的參數(shù),實(shí)現(xiàn)不同程度的對(duì)比度調(diào)整;
1.2:背景相減
? ? ? ?對(duì)圖像I和對(duì)應(yīng)的背景圖B,基于背景相減檢測(cè)I中的前景區(qū)域,設(shè)法改進(jìn)結(jié)果。
一、線性函數(shù)對(duì)比度亮度調(diào)節(jié):
code
#include<opencv2/core/core.hpp>
#include<opencv2/imgcodecs.hpp>
#include<opencv2/core/saturate.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int, char** argv)
{
double alpha = 1.0; /*< Simple contrast control */
int beta = 0; /*< Simple brightness control */
Mat image = imread("a.png");
//cvtColor(image, image, CV_BGR2GRAY);//轉(zhuǎn)為灰度圖
Mat new_image = Mat::zeros(image.size(), image.type());
cout << " Basic Linear Transforms " << endl;
cout << "-------------------------" << endl;
cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
cout << "* Enter the beta value [0-100]: "; cin >> beta;
for (int y = 0; y < image.rows; y++) {
for (int x = 0; x < image.cols; x++) {
for (int c = 0; c < 3; c++) {
new_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(alpha*(image.at<Vec3b>(y, x)[c]) + beta);
}
}
}
namedWindow("Original Image", WINDOW_AUTOSIZE);
namedWindow("New Image", WINDOW_AUTOSIZE);
imshow("Original Image", image);
imshow("New Image", new_image);
waitKey();
return 0;
}
二、sigmoid函數(shù)對(duì)比度亮度調(diào)節(jié):

(1)首先應(yīng)用公式

(引用自論文A New Approach for Contrast Enhancement Using Sigmoid Function——Naglaa Hassan and Norio Akamatsul)對(duì)每個(gè)像素點(diǎn)進(jìn)行處理,發(fā)現(xiàn)效果并不好,容易高亮丟失紋理(受參數(shù)C的影響太大),實(shí)用效果差如下圖:


(2)自行設(shè)計(jì)調(diào)整函數(shù):
t = I(x,y) / 255.00 * c_p * 0.1; //c_p為界面可動(dòng)態(tài)調(diào)整參數(shù)
O(x,y) = I(x,y) ( ( 1.00/ ( 1.00+exp ( -t) ) + 0.5 ) + b_value - 100)
應(yīng)用新公式測(cè)試效果如下:

(3)發(fā)現(xiàn)還是會(huì)有一些紋理丟失,思考后認(rèn)為255/200-1<0.3,所以應(yīng)該將0.5這個(gè)參數(shù)調(diào)低至0.3,調(diào)低為0.3后進(jìn)行測(cè)試效果較好,達(dá)到預(yù)期效果。:


code:
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include<math.h>
#include <iostream>
using namespace std;
using namespace cv;
static void ContrastAndBright(int, void *);
int c_p;
int b_value;
Mat s_image, t_imag;
int main()
{
s_image = imread("22.png");
if (!s_image.data)
{
cout << "圖片讀取失??!" << endl;
return false;
}
t_imag = Mat::zeros(s_image.size(), s_image.type());
c_p = 20;
b_value = 100;
namedWindow("效果圖窗口", WINDOW_AUTOSIZE);
createTrackbar("對(duì)比度", "效果圖窗口", &c_p, 200, ContrastAndBright);
createTrackbar("亮 度", "效果圖窗口", &b_value, 200, ContrastAndBright);
ContrastAndBright(c_p, 0);
ContrastAndBright(b_value, 0);
waitKey(0);
return 0;
}
static void ContrastAndBright(int, void *)
{
namedWindow("窗口02", WINDOW_AUTOSIZE);
// g_dstImage(i,j) =a*g_srcImage(i,j) + b
for (int y = 0; y < s_image.rows; y++)
{
for (int x = 0; x < s_image.cols; x++)
{
for (int c = 0; c < 3; c++)
{
//0<=c_p<=200
double t = ((s_image.at<Vec3b>(y, x)[c] - 127) / 225.00)*c_p*0.1;
t_imag.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(s_image.at<Vec3b>(y, x)[c] * ((1.00 / (1.00 + exp(-t))) + 0.3) + b_value - 100);
//int t = s_image.at<Vec3b>(y, x)[c];
//t_imag.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(t * ((c_p*0.1 / (1.00 + exp(-t))) + 1));
}
}
}
imshow("窗口02", s_image);
imshow("效果圖窗口", t_imag);
}
三、背景相減實(shí)驗(yàn):
1、相減得到圖一,下半未很好顯示,而后定義閾值后與(f_image(x,y)[c] - b_image(x,y)[c])比較,對(duì)RGB三通道分別賦值為0或255得到下圖效果:




2、調(diào)整改進(jìn)算法,原理如下:
對(duì)于去除噪聲點(diǎn),可以考慮使用中指濾波,對(duì)椒鹽噪聲有較好效果

將像素點(diǎn)得RGB值看為一向量,求前景與背景三通道差值得平方和,最后取平方根后與閾值進(jìn)行比較,大于閾值一并將三通道值都賦值為255,反之為0,最后效果如下:




可以看出當(dāng)閾值為75-100時(shí)效果最好。
code
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include<math.h>
#include <iostream>
using namespace std;
using namespace cv;
int maind22(){
Mat f_image, b_image;
f_image = imread("123.png");
b_image = imread("123b.png");
//Mat gray_f;
//cvtColor(f_image, gray_f, CV_BGR2GRAY); //彩色圖片轉(zhuǎn)換成黑白圖片
if (!f_image.data||!b_image.data)
{
cout << "讀取圖片失??!" << endl;
return -1;
}
if (f_image.rows != b_image.rows || f_image.cols != b_image.cols)
cout << "前景圖與后景圖尺寸不符,無(wú)法相減!" << endl;
Mat t_image = Mat::zeros(f_image.size(), f_image.type());
namedWindow("<效果圖窗口>", WINDOW_AUTOSIZE);
double sum = 0.0;
for (int y = 0; y < f_image.rows; y++)
{
for (int x = 0; x < f_image.cols; x++)
{
sum = 0.0;
for (int c = 0; c < 3; c++)
{
sum += pow((f_image.at<Vec3b>(y, x)[c] - b_image.at<Vec3b>(y, x)[c]), 2);
}
sum = sqrt(sum);
if (sum >= 75) {
for (int c = 0; c < 3; c++)
{
t_image.at<Vec3b>(y, x)[c] = saturate_cast < uchar>(255);
}
}
else {
for (int c = 0; c < 3; c++)
{
t_image.at<Vec3b>(y, x)[c] = saturate_cast < uchar>(0);
}
}
}
}
//cvtColor(t_image, t_image, CV_BGR2GRAY);
imshow("<效果圖窗口>", t_image);
waitKey(0);
return 0;
}