编程环境:
VS + OpenCV + C++
完整代码已经更新至GitHub,欢迎fork~GitHub链接
声明:创作不易,未经授权不得复制转载
statement:No reprinting without authorization
内容:
对比度及亮度的基本调整原理公式为:g(i,j) = af(i,j) + b*
->g 变换后图像
->f 变换前原图
->a 用于控制对比度
->b 用于控制亮度
1.1:对比度调整
设计一个Sigmoid函数,实现对图像的对比度调整;使用opencv窗口系统的slider控件,交互改变Sigmoid函数的参数,实现不同程度的对比度调整;
1.2:背景相减
对图像I和对应的背景图B,基于背景相减检测I中的前景区域,设法改进结果。
一、线性函数对比度亮度调节:
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);//转为灰度图
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函数对比度亮度调节:
(1)首先应用公式
(引用自论文A New Approach for Contrast Enhancement Using Sigmoid Function——Naglaa Hassan and Norio Akamatsul)对每个像素点进行处理,发现效果并不好,容易高亮丢失纹理(受参数C的影响太大),实用效果差如下图:
(2)自行设计调整函数:
t = I(x,y) / 255.00 * c_p * 0.1; //c_p为界面可动态调整参数
O(x,y) = I(x,y) ( ( 1.00/ ( 1.00+exp ( -t) ) + 0.5 ) + b_value - 100)
应用新公式测试效果如下:
(3)发现还是会有一些纹理丢失,思考后认为255/200-1<0.3,所以应该将0.5这个参数调低至0.3,调低为0.3后进行测试效果较好,达到预期效果。:
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("对比度", "效果图窗口", &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);
}
三、背景相减实验:
1、相减得到图一,下半未很好显示,而后定义阈值后与(f_image(x,y)[c] - b_image(x,y)[c])比较,对RGB三通道分别赋值为0或255得到下图效果:
2、调整改进算法,原理如下:
对于去除噪声点,可以考虑使用中指滤波,对椒盐噪声有较好效果
将像素点得RGB值看为一向量,求前景与背景三通道差值得平方和,最后取平方根后与阈值进行比较,大于阈值一并将三通道值都赋值为255,反之为0,最后效果如下:
可以看出当阈值为75-100时效果最好。
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); //彩色图片转换成黑白图片
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 << "前景图与后景图尺寸不符,无法相减!" << 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;
}