C++ opencv 图像代数运算——对比度调整和背景相减
对比度调整
实验要求:
设计一个Sigmoid函数,实现对图像的对比度调整;
–使用opencv窗口系统的slider控件,交互改变Sigmoid函数的参数,实现不同程度的对比度调整;
对比度含义:
调整之后的 sigmoid函数:
实验思路:
我构建了 sigmoid函数,使用了三层for循环,一层遍历行,一层遍历列,还有一层遍历通道数(3通道),加入滑动条来传入对比度和亮度的参数,然后 在相应位置乘以了c_p(决定对比度),b_value(决定亮度),并使用了saturate_cast<uchar>函数来防止溢出。
效果图:
其中 sigmoid 函数的 参数可以自己调制
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include"opencv2/imgproc/imgproc.hpp"
#include<cmath>
#include <iostream>
using namespace std;
using namespace cv;
int c_p;
int b_value;
Mat image, mask;
void IntensityAndContrast(int, void *)
{
namedWindow("原图", WINDOW_AUTOSIZE);
for (int y = 0; y < image.rows; y++)
{
for (int x = 0; x < image.cols; x++)
{
for (int c = 0; c < 3; c++)
{
double u = ((image.at<Vec3b>(y, x)[c] - 127.0) / 255.00)*c_p*0.1;
mask.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(image.at<Vec3b>(y, x)[c] * ((1.00 / (1.00 + exp(-u))) + 0.4) + b_value-100);
}
}
}
imshow("原图", image);
imshow("效果图", mask);
}
int main()
{
image = imread("G:\\图片\\longmao7.jpg");
if (!image.data)
{
cout << "图片读取失败!" << endl;
return false;
}
//cvtColor(image,image,CV_BGR2GRAY);
namedWindow("效果图", WINDOW_AUTOSIZE);
mask = Mat::zeros(image.size(), image.type());
//cvtColor(mask, mask, CV_BGR2GRAY);
c_p = 20;
b_value =100;
createTrackbar("Contrast", "效果图", &c_p, 100, IntensityAndContrast);
createTrackbar("Intensity", "效果图", &b_value, 200, IntensityAndContrast);
IntensityAndContrast(c_p, 0);
IntensityAndContrast(b_value, 0);
waitKey(0);
return 0;
}
背景相减
对图像I和对应的背景图B,基于背景相减检测I中的前景区域,并输出前景的mask.
分析你的方法可能产生误检的情况,并上网查阅背景相减的改进方法,设法改进结果。
测试数据见群文件bgs-data.zip
思路:
一、首先必须判断图片是否存在,还要判断读取的两张图片图像I和对应的背景图B,长宽是否相同。
二、使用三重for循环,一重循环行,一重循环列,一重循环通道数(读取三通道),读取出来的像素,I(x,y)-B(x,y),进行区域相减,再进行平方求和,最后开根号,即下图的的公式显示:
三、选择一个阈值进行判断,如果 sum值大于阈值,则为需要提取的图像,像素则设为255(白色),如果sum小于阈值,像素值则设为0(黑色),最后再输出图像即可
背景图
效果图:
代码如下:
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<cmath>
#include<iostream>
using namespace std;
using namespace cv;
Mat a_img, b_img;
Mat mask;
int value;
void test(int, void*) {
double su;
for (int y = 0; y < a_img.rows; y++) {
for (int x = 0; x < a_img.cols; x++) {
su = 0.0;
for (int c = 0; c < 3; c++) {
// 求平方和
su += pow((a_img.at<Vec3b>(y, x)[c] - b_img.at<Vec3b>(y, x)[c]), 2);
}
su = sqrt(su);
// 01_bg.jpg 阈值为110
// 02_bg.jpg 阈值为90
// 07_bg.jpg 阈值为100
// 08_bg.jpg 阈值为 100
//13_bg.jpg 阈值为120
if (su >= value) {
for (int c = 0; c < 3; c++) {
mask.at<Vec3b>(y, x)[c] = 255;
}
}
else {
for (int c = 0; c < 3; c++) {
mask.at<Vec3b>(y, x)[c] = 0;
}
}
}
}
imshow("效果图", mask);
}
int main() {
a_img = imread("F:\\计算机视觉\\实验三图片\\02.jpg");
b_img = imread("F:\\计算机视觉\\实验三图片\\02_bg.jpg");
namedWindow("效果图", WINDOW_AUTOSIZE);
namedWindow("原图", WINDOW_AUTOSIZE);
if (!a_img.data || !b_img.data) {
cout << "读图失败" << endl;
return -1;
}
if (a_img.rows != b_img.rows || a_img.cols != b_img.cols) {
cout << "图片长度和宽度不符合" << endl;
return -1;
}
value = 100;
mask = Mat::zeros(a_img.size(), a_img.type());
createTrackbar("背景相减", "效果图", &value, 200, test);
test(value, 0);
imshow("原图", a_img);
imshow("背景图", b_img);
waitKey(0);
system("pause");
return 0;
}