opencv学习笔记(6):图像预处理(直方图、图像去噪)

3.直方图

直方图是用来表现图像中亮度分布的,给出的是图像中某个亮度或者某个范围亮度下共有几个像素,即统计一幅图某个亮度像素的数量

直方图不能反映某一灰度值像素在图像中的位置,失去了图像的空间信息。图像直方图由于其计算代价较小,且具有图像平移、旋转、缩放不变性等众多优点,被广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类。 

3.1 标准直方图 

 OpenCV中的直方图函数calcHist()定义如下。

void cv::calcHist(const Mat * images,
int     nimages,
const int * channels,
InputArray mask,
OutputArray hist,
int      dims,
const int * histSize,
const float ** ranges,
bool    uniform = true,
bool    accumulate = false)

具体参数解析如下:

  • const Mat *images:要求Mat指针。可以传递一个数组,可以同时求很多幅图像的直方图,前提是深度相同,如CV_8U和CV_32F,尺寸相同,通道数可以不同。
  • int nimages:源图像数。
  • const int* channels:传递要加入直方图计算的通道。该函数可以求多个通道的直方图,通道编号从0开始依次递增。假如第一幅图像有3个通道,第二幅图像有两个通道,则:images[0]的通道编号为0、1、2,images[1]的通道编号则为3、4;如果想通过5个通道计算直方图,则传递的通道channels为int channels[5] = {0,1,2,3,4,5}。
  • InputArray mask:掩码矩阵。没有掩码,则传递空矩阵就行了;如果非空,则掩码矩阵大小必须和图像大小相同,在掩码矩阵中,非空元素将被计算到直方图内。
  • OutputArray hist:输出直方图。
  • int dims:直方图维度。必须大于0,并小于CV_MAX_DIMS(32)。
  • const int*histSize:直方图中每个维度的级别数量。例如灰度值(0—255),如果级别数量为4,则灰度值直方图会按照[0, 63]、[64,127]、[128,191]、[192,255]划分,也称为bin数目,级别数量为4就是4个bin。如果是多维的就需要传递多个histSize,每个维度的大小用一个int型数据来表示,所以histSize是一个数组。
  • const float**ranges:一个维度中的每一个bin的取值范围。
  • bool uniform:如果为 true,则range可以用一个具有两个元素(一个最小值和一个最大值)的数组表示,如果为false,则需要用一个具有histSize+1个元素(每相邻两个元素组成的取值空间代表对应的bin的取值范围)的数组表示。如果统计多个维度则需要传递多个数组,所以ranges是一个二维数组。
  • bool accumulate:决定在计算直方图时是否清空传入的hist。其值为true表示不清空,为false则表示清空。该参数一般设置为false,只有在想要统计多个图像序列中的累加直方图时才会设置为true。

OpenCV中,在进行直方图绘图之前,需要用函数normalize ()对数据进行归一化处理。简单来说就是将数据限制在一定范围内,方便处理。normalize()函数声明如下。 

void cv::normalize(InputArray src,
InputOutputArray dst,
double alpha=1,
double beta=0,
int norm_type=NORM_L2,
int dtype=-1,
InputArray mark=noArray())

具体参数解析如下:

  • InputArray src:输入数组。
  • OutputArray dst:输出数组。大小和原数组一致。
  • double alpha:用来规范值或者规范范围,并且是下限。
  • double beta:用来规范范围并且是上限。因此该参数只在NORM_MINMAX中起作用。
  • int norm_type:归一化选择的数学公式类型。
  • int dtype:其值为负,输出的大小、深度、通道数都等于输入;其值为正,输出只有深度与输入不同,不同的地方由dtype决定。
  • InputArray mark:掩码。选择感兴趣区域,选定后只能对该区域进行操作。

 示例代码:

void function2()
{//读取一张图片Mat src = imread("C:/Users/27844/Desktop/icon.jpg");if(src.empty()){cout<<"image is empty"<<endl;return;}//分离图片通道vector<Mat> channels;split(src,channels);//计算直方图int histSize = 256; //直方图的bin数float range[] = {0,9}; //设置值的范围const float* histRange = { range };Mat b_hist, g_hist, r_hist;//创建Mat对象分别保存直方图,每个通道均为1calcHist(&channels[0],1,0,Mat(),b_hist,1,&histSize,&histRange,true,false);calcHist(&channels[1],1,0,Mat(),g_hist,1,&histSize,&histRange,true,false);calcHist(&channels[2],1,0,Mat(),r_hist,1,&histSize,&histRange,true,false);//数据归一化normalize(b_hist,b_hist,0,255,NORM_MINMAX,-1,Mat());normalize(g_hist,g_hist,0,255,NORM_MINMAX,-1,Mat());normalize(r_hist,r_hist,0,255,NORM_MINMAX,-1,Mat());//绘制直方图int hist_height=400,hist_width=512;int bin_width = cvRound((double)hist_width/hist_height); //bin的宽度Mat histImage(hist_width,hist_width,CV_8UC3,Scalar(255,255,255)); // 白色背景for(int i=1;i<histSize;i++){line(histImage,Point(bin_width * (i - 1), hist_height - cvRound(b_hist.at<float>(i - 1))),Point(bin_width * (i), hist_height - cvRound(b_hist.at<float>(i))),Scalar(255, 0, 0), 2, 8, 0);line(histImage,Point(bin_width * (i - 1), hist_height - cvRound(g_hist.at<float>(i - 1))),Point(bin_width * (i), hist_height - cvRound(g_hist.at<float>(i))),Scalar(0,255,0), 2, 8, 0);line(histImage,Point(bin_width * (i - 1), hist_height - cvRound(r_hist.at<float>(i - 1))),Point(bin_width * (i), hist_height - cvRound(r_hist.at<float>(i))),Scalar(0, 0,255), 2, 8, 0);}namedWindow("histImage",WINDOW_AUTOSIZE);imshow("histImage",histImage);waitKey(0);}

3.2 直方图均衡化

 直方图均衡化是一种增强图像对比度的方法,也叫直方图线性变换。其主要思想是将一幅图像的直方图分布变成近似均匀分布,从而增强图像的对比度,其基本原理是对在图像中像素个数多的灰度值(即对画面起主要作用的灰度值)进行展宽,而对像素个数少的灰度值(即对画面不起主要作用的灰度值)进行归并,从而加强对比度,使图像清晰,达到图像增强的目的。

OpenCV提供了一个直方图均衡化的函数,可以通过使用这个函数来实现直方图均衡化,函数定义如下。

cv::equalizeHist(image,result);

 参数解析如下:

  • image:输入图像,即源图像,必须是8位的单通道图像。
  • result:函数调用后的运算结果,需和源图像有一样的尺寸和类型。

 示例代码:

void function3()
{//直方图均衡化Mat src,dst;src = imread("C:/Users/27844/Desktop/icon.jpg");if(src.empty()){cout<<"image is empty"<<endl;return;}//将图片转换为灰度图并显示cvtColor(src,src,COLOR_BGR2GRAY);imshow("src",src);//进行直方图均衡化equalizeHist(src,dst);imshow("dst",dst);waitKey(0);destroyAllWindows();
}

3.3 直方图匹配

直方图的均衡化自动确定了变换函数,可以很方便地得到变换后的图像。但是,在有些应用中这种自动的增强并不是最好的方法。有时候,需要图像具有某一特定的直方图形状(也就是灰度分布),而不是均匀分布的直方图,这时可以使用直方图匹配。

直方图匹配也叫作直方图规定化,用于将图像变换为某一特定的灰度分布,适用于目标灰度直方图已知的情况。

直方图匹配的步骤如下:

(1)将源图像的灰度直方图进行均衡化,得到一个变换函数 s = T ( r ),其中 s 是均衡化后的像素, r 是原始像素。

(2)对规定的直方图进行均衡化,得到一个变换函数 v = G ( z ),其中 v 是均衡化后的像素, z 是规定的像素。

(3)上面都是对同一图像的均衡化,其结果应该是相等的,即 s = v ,且 z = G -1 ( v )= G -1 [ T ( r )]。

3.4 局部直方图处理

 全局直方图适用于整张图像的增强,但有时存在这样的情况:只需要增强图像中小区域的细节。在这些区域中,一些像素的影响在全局变换的计算中可能被忽略了,因为全局直方图没有必要保证期望的局部增强,解决方法是以图像中每个像素的邻域中的灰度分布为基础设计变换函数。处理过程是定义一个邻域,并把该区域的中心从一个像素移至另一个像素。在每个位置,计算邻域中点的直方图,并且得到的不是直方图的均衡化就是规定化的变换函数,这个函数最终用于映射邻域中心像素的灰度。然后,邻域的中心被移至一个相邻像素位置,重复该过程。当邻域进行逐像素平移时,由于只有邻域中的一行或一列改变,所以可以在移动一步的过程中以新数据更新前一个位置得到的直方图。

局部直方图操作的具体步骤如下:

(1)求第一个邻域内的直方图。

(2)根据直方图均衡化将该邻域中心点的像素更新。

(3)将中心点移向下一个邻域,例如,此时中心点为(3,3)(第一个数为行,第二个值为列),先向下移动一个像素,中心点变为(4,3),假设局部直方图大小为7×7,则此时得到的邻域与前一个邻域相比只有一行像素不同,即(0,0)、(0,1)……(0,6)与(7,0)、(7,1)……(7,6)可能不同,此时比较第0行和第7行相对应的元素是否相同来更新直方图,如果直方图有变化,则更新当前中心点的像素值。

(4)对所有的像素执行第三歩。

 

4. 图像去噪 

 图像去噪是指减少数字图像中噪声的过程。现实中的数字图像在数字化和传输过程中常受到成像设备与外部环境噪声等的影响,在这种条件下得到的图像称为含噪图像或噪声图像。噪声是干扰图像的重要因素。一幅图像在实际应用中可能存在各种各样的噪声,这些噪声可能在传输过程中产生,也可能在量化处理等过程中产生。

下面举例几种常用的:

4.1 均值滤波

均值滤波是由当前像素邻近的若干像素组成的模板的均值来替代原像素的值的方法。在opencv中,用blur()函数进行均值滤波。

 均值滤波卷积核:

 注意:在处理噪声的同时也存在一个问题,就是源图像的一些细节变得模糊了。

4.2 高斯滤波

高斯滤波是线性滤波中的一种。在OpenCV图像滤波处理中,高斯滤波用于平滑图像,或者说是进行图像模糊处理。

其原理是将正态分布(又名高斯分布)用于图像处理,相当于在图像上产生“模糊”效果,“中间点”会失去细节,所以高斯滤波属于低通滤波,低通滤波就是去掉高频信号,留下低频信号。相反,高通滤波就是去掉低频信号,留下高频信号。

在opencv中,用GaussianBlur()函数进行高斯滤波。函数定义如下。

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT)

参数解析如下。

InputArray src:输入图像。图像可以具有任何数量的通道。
OutputArray dst:输出图像。与输入图像大小、类型相同。
Size ksize:高斯核大小。ksize.width 和 ksize.height 可以有所不同,但它们都必须是正数和奇数。
double sigmaX: x 方向上的高斯核标准偏差。
double sigmaY: y 方向上的高斯核标准偏差。
如果sigmaY为0,则将其设置为与sigmaX相同的值;如果sigmaX和sigmaY都是0,则分别根据ksize.width和ksize.height计算而来。
int borderType:用于推断图像外部像素的某种边界模式。

高斯滤波对被高斯噪声污染的图像具有很好的处理效果。均值滤波是基于平均权重,无法克服边缘像素信息丢失的缺陷。高斯滤波部分克服了该缺陷,但是无法完全克服,因为没有考虑像素值的不同,对边缘信息权值较低。

4.3 中值滤波

 中值滤波在某些情况下可以做到既能去除噪声又能保护图像的边缘,是一种非线性的去除噪声的方法。在opencv中,用medianBlur()函数进行高斯滤波。

 中值滤波相较于均值滤波在去除噪声的同时更多地保留了图像的细节。中值滤波处理对滤除脉冲噪声比较有效。脉冲噪声也称椒盐噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是在亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。

4.4  双边滤波

 双边滤波是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。在opencv中,使用bilateralFilter()函数来进行双边滤波。

 示例代码:

void function4()
{// 图像去噪// 1.均值滤波Mat src = imread("C:/Users/27844/Desktop/icon.jpg");if(src.empty()){cout<<"image is empty"<<endl;return;}imshow("src",src);Mat dst;dst.create(src.size(),src.type());blur(src,dst,Size(7,7));imshow("blur",dst);// 2.高斯滤波Mat dst2;dst2.create(src.size(),src.type());GaussianBlur(src,dst2,Size(7,7),0,0);imshow("GaussianBlur",dst2);// 3.中值滤波Mat dst3;dst3.create(src.size(),src.type());medianBlur(src,dst3,7);imshow("medianBlur",dst3);// 4.双边滤波Mat dst4;dst4.create(src.size(),src.type());bilateralFilter(src,dst4,9,60,15);imshow("bilateralFilter",dst4);waitKey(0);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/884247.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《双指针篇》---移动零

题目传送门 这道题可以归类为 数组划分/数组分块 。 题目制定了一个规则&#xff0c;我们可以在这个规则下&#xff0c;将数组划分为若干个区间。 这道题让我们把所有非零元素移动到左边。所有零元素移动到右边。 将数组划分为&#xff1a; 左区间非0&#xff1b; 右区间&…

OpenHarmony、HarmonyOS、HarmonyNext互相兼容吗?

1&#xff0c;三者之间的关系 OpenHarmony&#xff1a;开源底层。HarmonyOS&#xff1a;闭源手机系统&#xff0c;兼容安卓生态。HarmonyOS NEXT&#xff1a;纯血鸿蒙&#xff0c;不兼容安卓。 上一篇文章简单介绍过&#xff0c;就不再多说了&#xff0c;这里说一下HarmonyOS …

Camera学习笔记(202410)

课程&#xff1a;CameraX&#xff1a;面向开发者的摄像头支持库 链接&#xff1a;CameraX&#xff1a;面向开发者的摄像头支持库_哔哩哔哩_bilibili 课程时长&#xff1a;28:00 学习时间&#xff1a;2024-10-29 概述&#xff1a;2019年Android CameraX的发布会 个人感觉&a…

Django入门教程——用户管理实现

第六章 用户管理实现 教学目的 复习数据的增删改查的实现。了解数据MD5加密算法以及实现模型表单中&#xff0c;自定义控件的使用中间件的原理和使用 需求分析 系统问题 员工档案涉及到员工的秘密&#xff0c;不能让任何人都可以看到&#xff0c;主要是人事部门进行数据的…

BugKu练习记录:矛盾

题目&#xff1a; $num$_GET[num]; if(!is_numeric($num)) { echo $num; if($num1) echo flag{**********}; }关键在于绕过is_numeric&#xff0c;PHP中字符串与数字弱比较&#xff0c;会将字符串转换为数字&#xff0c;截至到非数字字符&#xff0c;如果第一个字符就是非数字…

安宝特分享 | AR技术引领:跨国工业远程协作创新模式

在当今高度互联的工业环境中&#xff0c;跨国合作与沟通变得日益重要。然而&#xff0c;语言障碍常常成为高效协作的绊脚石。安宝特AR眼镜凭借其强大的多语言自动翻译和播报功能&#xff0c;正在改变这一局面&#xff0c;让远程协作变得更加顺畅。 01 多语言翻译优势 安宝特A…

逗号运算符应用举例

在main.cpp里输入程序如下&#xff1a; #include <iostream> //使能cin(),cout(); #include <iomanip> //使能setbase(),setfill(),setw(),setprecision(),setiosflags()和resetiosflags(); //setbase( char x )是设置输出数字的基数,如输出进制数则用set…

vxe-table v4.8+ 与 v3.10+ 虚拟滚动支持动态行高,虚拟渲染更快了

Vxe UI vue vxe-table v4.8 与 v3.10 解决了老版本虚拟滚动不支持动态行高的问题&#xff0c;重构了虚拟渲染&#xff0c;渲染性能大幅提升了&#xff0c;行高自适应和列宽拖动都支持&#xff0c;大幅降低虚拟渲染过程中的滚动白屏&#xff0c;大量数据列表滚动更加流畅。 自适…

ICPC区域赛成都站【赛后回顾+总结】

传送门 前言赛后总结赛后回顾赛后感悟 前言 首先&#xff0c;这是本人本赛季第一场XCPC区域赛&#xff0c;也是本人算竞生涯中第一场XCPC区域赛&#xff08;之前只打过邀请赛和省赛&#xff09;。 赛后总结 然后赛后总结一下&#xff1a;我队天崩开局&#xff0c;我队出师不利…

c盘满了怎么清理垃圾而不误删?6招轻松清理C盘,快来试试

c盘满了怎么清理垃圾而不误删&#xff1f;相信平时工作生活中离不开电脑&#xff0c;随着使用电脑时间就了&#xff0c;C 盘的空间会不断被占据&#xff0c;进而致使系统运行变得迟缓&#xff0c;甚至出现卡顿现象。因此&#xff0c;定期清理 C 盘的是非常重要的。很多电脑小白…

excel的宏1

1宏和vba visual basic for applications 一种编程语言 2vba编写一系列指令的程序&#xff0c;就是宏 3完成重复性的数据任务 点击开发工具 使用设置的宏之后表格的变化 excel帮忙编写了一个代码 以上为自动编写的代码

Swarm-LIO: Decentralized Swarm LiDAR-inertial Odometry论文翻译

文章目录 前言一、介绍二、相关工作三、方法A. 问题表述B. 框架概述C. 群体系统的初始化D. 去中心化激光雷达-惯性状态估计 四. 实验A. 室内飞行B. 退化环境飞行C. 去中心化部署 五. 结论和未来工作 前言 原文&#xff1a;原文 准确的自我状态和相对状态估计是完成群体任务的关…

光耦合器的关键作用和创新---腾恩科技

光耦合器或光隔离器已成为电路中必不可少的器件&#xff0c;它允许信号在无需直接电接触的情况下跨不同电压域传输。这种隔离能力对于保护低压元件免受高压电路的潜在损坏至关重要。本文将仔细研究光耦合器在当今技术中发挥的独特作用&#xff0c;并探讨其在各种应用中不断扩展…

linux:回车换行+进度条+git理解与使用以及如何解决免密码push问题

目录 特殊符号 Linux小程序---进度条 1.\n和\r的理解 2.缓冲区 3.设计简单的倒计时 4.设计简单的进度条 git-版本控制器 1.理解什么是版本控制器? 2.git的使用 3.git的其他说明 总结上传过程 特殊符号 1.(取消显化) 的作用:执行指令,但指令本身不会显化; 举个例子:我…

vscode摸鱼学习插件开发

不知道大家在摸鱼的时候&#xff0c;会不会想要学习&#xff1f; 或者有没有考公人&#xff0c;下班要学习的&#xff1f; 上班时间摸鱼&#xff0c;下班时间不够学习&#xff1f; 为此&#xff0c;我决定开发一个vscode插件&#xff0c;来刷粉笔题 粉笔插件名称&#xff1a;…

如何解决RabbitMQ消息的重复消费问题

什么情况下会导致消息的重复消费——在消费者还没成功发送自动确认机制时发生&#xff1a; 网络抖动消费者挂了 解决方案 每条消息设置一个唯一的标识id幂等方案&#xff1a;【Redis分布式锁、数据库锁&#xff08;悲观锁、乐观锁&#xff09;】 面试官&#xff1a;如何解决…

Kafka 与传统 MQ 消息系统之间有三个关键区别?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka 与传统 MQ 消息系统之间有三个关键区别&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; Kafka 与传统 MQ 消息系统之间有三个关键区别&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 …

软件测试基础知识最强总结(2024版)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、什么是软件&#xff1f; 软件是计算机系统中的程序和相关文件或文档的总称。 二、什么是软件测试&#xff1f; 说法一&#xff1a;使用人工或自动的手段…

智慧用电监控装置:引领0.4kV安全用电新时代

在智能科技日新月异的今天&#xff0c;电力安全与管理正迎来一场前所未有的革新。为0.4kV以下TT、TN系统打造的智慧用电在线监控装置不仅重新定义了电力监控的边界&#xff0c;更为建筑安全用电筑起了一道坚不可摧的防线。 装置集成了单、三相交流电精确测量、四象限电能计量、…

【GL09】(算法)卡尔曼滤波

一、简介 卡尔曼滤波&#xff08;Kalman Filter&#xff09;是一种有效的递归滤波器&#xff08;自回归滤波器&#xff09;&#xff0c;它能够从一系列的包含统计噪声的测量中估计动态系统的状态。卡尔曼滤波广泛应用于信号处理、控制理论、自动驾驶、金融等领域。 基本公式&am…