当前位置: 首页 > news >正文

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

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

实验题目: 实验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);
}


相关文章:

  • HTTP协议3)----对于网络层的详细讲解
  • [单片机框架][device层] charger 电源管理
  • [单片机框架][drivers层][bq25601] charger 电源管理
  • Java多线程--InheritableThreadLocal--使用/实例
  • java计算机毕业设计宿迁学院学生设计作品交流网站源代码+数据库+系统+lw文档
  • ByteTrack:通过关联每个检测框进行多对象跟踪
  • 新能源汽车行业资讯-2022-9-22
  • Ajax学习笔记(一)
  • 【【计算机组成原理】中央处理器(二)—— 指令执行过程
  • YOLOv5、v7改进之二十八:ICLR 2022涨点神器——即插即用的动态卷积ODConv
  • php警车管理系统设计与实现
  • 提高PHP编程效率的技巧
  • 安防单位怎么实施RPA新员工提升企业运作效率
  • 线程安全问题的原因和解决方案
  • zabbix配置邮件告警
  • .pyc 想到的一些问题
  • 4. 路由到控制器 - Laravel从零开始教程
  • conda常用的命令
  • EventListener原理
  • Hibernate最全面试题
  • Js基础——数据类型之Null和Undefined
  • php的插入排序,通过双层for循环
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 安卓应用性能调试和优化经验分享
  • 创建一种深思熟虑的文化
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 小程序测试方案初探
  • 因为阿里,他们成了“杭漂”
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 【干货分享】dos命令大全
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #单片机(TB6600驱动42步进电机)
  • $.ajax()
  • (16)Reactor的测试——响应式Spring的道法术器
  • (9)目标检测_SSD的原理
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (超详细)语音信号处理之特征提取
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)一些感悟
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET Core 项目指定SDK版本
  • .Net Web窗口页属性
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @Autowired和@Resource的区别
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...
  • @NestedConfigurationProperty 注解用法
  • @Responsebody与@RequestBody
  • [20180224]expdp query 写法问题.txt