数字图像处理-对比度调整&背景相减

数字图像处理-对比度调整&背景相减

实验题目: 实验E2:图像代数运算

实验2.1:对比度调整

实验过程中遇到和解决的问题:

对比度调整因为给的图片没有上课所说的细节,实验要求没有指出,这里存在问题如果图片细节较多,可能会细节缺失,通过亮度加以调整,sigmod函数的数学形式分析,关于像素范围与sigmod原函数范围的转化

sigmod函数:
F ( x ) = 1 1 + e − x F(x)=\frac{1}{1+e^{-x}} F(x)=1+ex1
在这里插入图片描述

将像素值转化到[-1,1], 然后通过系数进行缩放,系数越大,正值越大,负值越小,对应sigmod函数上的取值差异越大,表现为像素值大于127的更亮,小于127的更暗, 图像对比度增强,反之;

图像亮度是图像整体像素值的增大或者减小,这里直接在转化后图像像素值加一个值来控制亮度, 代码实现为:

                double t = ((g_srcImage.at<Vec3b>(y, x)[c] - 127) / 225.00) * g_nContrastValue * 0.1;
                g_dstImage.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(g_srcImage.at<Vec3b>(y, x)[c] * ((1.00 / (1.00 + exp(-t))) + 0.5) + g_nBrightValue - 100);

数值溢出问题

通过saturate_cast来控制范围.

结果分析与体会:

在这里插入图片描述

增强对比度:
在这里插入图片描述

增强亮度:
在这里插入图片描述

  • 可以看到对比度让明暗对比更明显; 亮度是整体变化.

更多实验:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

实验2.2:背景相减

实验过程中遇到和解决的问题:

图像背景稍微有变动,产生噪声干扰。

通过上网了解到图像平滑,通过中值滤波,对图像边界特征还没有完全消失的时候,对背景做平滑处理;

cv::medianBlur(front_mask, new_front_mask, 3);
图像的亮度曝光度不同导致背景不能完全去除。

背景相减之后要通过一个阈值处理然后产生mask,可以解决明暗问题。

图像的一些边界不能显示。

阈值调整, 中值平滑, 暂时没有很好的解决思路.

核心代码:

	cv::absdiff(image, image_bg, front_mask);
/*	imshow("New Image", front_mask);
	waitKey(0);*/
	//通过每个通道的平方和最后开方设定阈值
	for (int y = 0; y < image.rows; y++) {
		for (int x = 0; x < image.cols; x++) {
			int tsum = 0;
			for (int c = 0; c < 3; c++) {
				tsum += front_mask.at<Vec3b>(y, x)[c]* front_mask.at<Vec3b>(y, x)[c];
			}
			tsum = sqrt(tsum);
			if (tsum < value) {
				front_mask.at<Vec3b>(y, x)[0] = 0; front_mask.at<Vec3b>(y, x)[1] = 0; front_mask.at<Vec3b>(y, x)[2] = 0;
			}
			else {
				front_mask.at<Vec3b>(y, x)[0] = 255; front_mask.at<Vec3b>(y, x)[1] = 255; front_mask.at<Vec3b>(y, x)[2] = 255;
			}
		}
	}

结果分析与体会:

在这里插入图片描述

  • 影子的背景干扰很难去除
  • 通过中值滤波平滑得到对于背景的很多噪声做了处理;
  • 裤子的阴影部分边界模糊
    在这里插入图片描述

更多实验:
在这里插入图片描述

在这里插入图片描述

  • 前景部分零件不能很好的抽离出来
  • 可以针对特定场景限定, 比如针对分离后的图像做最大值滤波, 但没有普适性.
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码

brackground:

#include<opencv2/core/core.hpp>
#include<opencv2/imgcodecs.hpp>
#include<opencv2/core/saturate.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream> 
#include <opencv2/imgproc.hpp>
#include<cmath>
using namespace std;
using namespace cv;

int alpha = 10; //< Simple contrast control 
int beta = 0;       //< Simple brightness control 
string impath = "D:\\CV\\13.jpg";  //1 2 7 8 13
string im_bgpath = "D:\\CV\\13_bg.jpg";
Mat image = imread(impath); //"D:\\CV\\01.jpg"
Mat new_image = Mat::zeros(image.size(), image.type()); //创建新的图像
int value = 10;
Mat image_bg, front_mask;


void Backgroundsustraction(int,void*) {
	//cout << "value:" << value << "\n";
	//计算两幅图片差异位置的RGB值输出到front_mask中
	cv::absdiff(image, image_bg, front_mask);
/*	imshow("New Image", front_mask);
	waitKey(0);*/
	//通过每个通道的平方和最后开方设定阈值
	for (int y = 0; y < image.rows; y++) {
		for (int x = 0; x < image.cols; x++) {
			int tsum = 0;
			for (int c = 0; c < 3; c++) {
				tsum += front_mask.at<Vec3b>(y, x)[c]* front_mask.at<Vec3b>(y, x)[c];
			}
			tsum = sqrt(tsum);
			if (tsum < value) {
				front_mask.at<Vec3b>(y, x)[0] = 0; front_mask.at<Vec3b>(y, x)[1] = 0; front_mask.at<Vec3b>(y, x)[2] = 0;
			}
			else {
				front_mask.at<Vec3b>(y, x)[0] = 255; front_mask.at<Vec3b>(y, x)[1] = 255; front_mask.at<Vec3b>(y, x)[2] = 255;
			}
		}
	}
	Mat new_front_mask = Mat::zeros(front_mask.size(), front_mask.type());
	Mat new_front_mask2 = Mat::zeros(front_mask.size(), front_mask.type());
	cv::medianBlur(front_mask, new_front_mask, 3);
	//cv::Canny(new_front_mask, new_front_mask2, 1, 3, 3);
	namedWindow("After blur Image", WINDOW_AUTOSIZE);//去噪声
	imshow("New Image", front_mask);
	imshow("After blur Image", new_front_mask);
}

int main(int, char** argv)
{
	image_bg = imread(im_bgpath);
	front_mask = Mat::zeros(image.size(), image.type());
	namedWindow("Original Image", WINDOW_AUTOSIZE);
	namedWindow("New Image", WINDOW_AUTOSIZE);
	createTrackbar("threshold", "New Image", &value, 1000, Backgroundsustraction);
	Backgroundsustraction(value,0);
	
	imshow("Original Image", image);
	waitKey(0);

	return 0;
}

contrast:

//-----------------------------------【头文件包含部分】---------------------------------------
//  描述:包含程序所依赖的头文件
//---------------------------------------------------------------------------------------------- 
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

//-----------------------------------【命名空间声明部分】---------------------------------------
//  描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------   
using namespace std;
using namespace cv;

//-----------------------------------【全局函数声明部分】--------------------------------------
//  描述:全局函数声明
//-----------------------------------------------------------------------------------------------
static void ContrastAndBright(int, void*);

//-----------------------------------【全局变量声明部分】--------------------------------------
//  描述:全局变量声明
//-----------------------------------------------------------------------------------------------
int g_nContrastValue; //对比度值
int g_nBrightValue;  //亮度值
Mat g_srcImage, g_dstImage;
//-----------------------------------【main( )函数】--------------------------------------------
//  描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main1()
{
    //改变控制台前景色和背景色
    //system("color 2F");
    // 读入用户提供的图像
    g_srcImage = imread("D:\\CV\\IP_data\\bgs_data\\13.jpg");//2 7 8 13
    if (!g_srcImage.data) { printf("读取g_srcImage图片错误~! \n"); return false; }
    g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type());

    //设定对比度和亮度的初值
    g_nContrastValue = 80;
    g_nBrightValue = 80;

    //创建窗口
    namedWindow("【效果图窗口】", 1);

    //创建轨迹条
    createTrackbar("对比度:", "【效果图窗口】", &g_nContrastValue, 300, ContrastAndBright); // 取值0~300
    createTrackbar("亮   度:", "【效果图窗口】", &g_nBrightValue, 200, ContrastAndBright); // 取值0~200

    //调用回调函数
    ContrastAndBright(g_nContrastValue, 0);
    ContrastAndBright(g_nBrightValue, 0);

    //输出一些帮助信息
    cout << endl << "\t运行成功,请调整滚动条观察图像效果\n\n"
        << "\t按下“q”键时,程序退出\n";

    //按下“q”键时,程序退出
    while (char(waitKey(1)) != 'q') {}
    return 0;
}

//-----------------------------【ContrastAndBright( )函数】------------------------------------
//  描述:改变图像对比度和亮度值的回调函数
//-----------------------------------------------------------------------------------------------
static void ContrastAndBright(int, void*)
{

    // 创建窗口
    namedWindow("【原始图窗口】", 1);

    // 三个for循环,执行运算 g_dstImage(i,j) = a*g_srcImage(i,j) + b
    for (int y = 0; y < g_srcImage.rows; y++)
    {
        for (int x = 0; x < g_srcImage.cols; x++)
        {
            for (int c = 0; c < 3; c++)
            {
                // sigmoid 函数控制对比度, 常量g_nBrightValue控制亮度
                double t = ((g_srcImage.at<Vec3b>(y, x)[c] - 127) / 225.00) * g_nContrastValue * 0.1;
                g_dstImage.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(g_srcImage.at<Vec3b>(y, x)[c] * ((1.00 / (1.00 + exp(-t))) + 0.5) + g_nBrightValue - 100);
            }
        }
    }

    // 显示图像
    imshow("【原始图窗口】", g_srcImage);
    imshow("【效果图窗口】", g_dstImage);
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值