OpenCV计算机视觉开发入门与实践<十七>:点运算与灰度变换概述

  灰度化是图像处理中的一个基本步骤,其目的是将彩色图像转换为灰度图像。灰度图像是一种仅包含亮度信息而不包含颜色信息的图像,其像素值通常用一个字节(即0~255的范围)来表示,这个值代表了该像素的灰度等级,也就是亮度。灰度化是许多图像处理任务的第一步,如边缘检测、图像分割、特征提取等,因为灰度图像相对于彩色图像来

说,计算量更小,处理速度更快,同时保留了图像的大部分重要信息。

  灰度变换可以改善图像的质量,使图像能够显示更多的细节,提高图像的对比度(对比度拉伸);可以有选择地突出图像感兴趣的特征,或者抑制图像中不需要的特征;可以有效地改变图像的直方图分布,使像素的分布更为均匀。

1.点运算

1.1 基本概念

  图像点运算(或称点处理)是指对图像中的每一个像素点依次进行同样的灰度运算,使其输出的每一个像素值仅由对应点的值来决定,可以理解为点到点之间的映射。在所有图像处理算法中,点运算是基本的图像处理操作,它既可以单独使用,又可以与其他算法组合使用。通过点运算,输出图像每个像素的灰度值仅仅取决于输入图像中对应像素的灰度值。因此,点运算不能改变图像内的空间关系。

  点运算是基于像素的处理,进行这类处理时,每个像素的处理与其他像素无关。点运算以预定的方式改变图像的灰度直方图,除了灰度级的改变是根据某种特定的灰

度变换函数进行的以外,点运算可以被视为一种"从像素到像素"的复制操作。

1.2 点运算的目标

  点运算是实现图像增强处理的常用方法之一,经常用于改变图像的灰度范围及其分布。通过这种方法可以使图像的动态范围增大,增强图像的对比度,使图像变得更加清

晰。

1.3 点运算的分类

  通常点运算分为灰度变换和直方图修正两种,其中直方图修正包括直方图均衡化和直方图规定化。

  灰度变换是图像处理的基本方法之一,可加大图像动态范围,增强对比度,使得图像更加清晰,特征更加明显,是图像增强的重要手段。图像的灰度变换又称为灰度增强,是指根据某种目标条件,按一定变换关系逐点改变原图像中每一个像素灰度值的方法。

  直方图均衡化也是一种灰度的变换过程,它将当前的灰度分布通过一个变换函数变换为范围更宽、灰度分布更均匀的图像。也就是将原图像的直方图修改为在整个灰度区间内大致均匀分布,因此扩大了图像的动态范围,增强了图像的对比度。

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

1.4 点运算的特点

  从算法原理来看,点运算指的是仅根据图像中像素的原灰度值,按一定的规则来确定其新的灰度值。在实现点运算算法时,有时还得考虑像素在图像中的位置。由于点运算算法的上述特点,单个像素的新灰度值仅仅依赖于该像素原灰度值的大小,而与周围像素的灰度值没有关系。正因为像素原灰度值与新灰度值间是单独相关的,故点运算算法一般是

可逆的。

  点运算算法通常采取逐点扫描像素的方法来实现每个像素的变换,它直接把原像素值映射到一个新值,因此点运算可以借助查找表实现。一般来讲,点运算算法不会改变一幅图像中各像素之间的空间关系,因此不能用于增强图像所包含的细节。有时,这种处理又被称为对比度拉伸、对比度增强或灰度变换等。

1.1.5 点运算的应用

  在开始处理图像前,有时需要用点运算来克服图像数字化设备的局限性,这对于图像的显示十分重要。点运算通常有如下应用:

1)光度学标定

  数字图像中每一像素的灰度值应该反映原稿和数字化设备的物理特性,例如光照强度和反射(或透射)密度等。利用点运算可以去除图像输入设备传感器的非线性影响。假设一幅图像被一个对光照强度呈非线性反应的仪器数字化,则可以利用点运算来变换灰度级,使之反映光照强度的等步长增量,这就是光度学标定。此外,点运算也可以用来产生一幅图像,该图像的灰度级表示原稿反射(或透射)密度的等步长增量。

2)对比度增强

  在某些数字图像中,人们感兴趣的特征仅占据整个灰度分级相当窄的一个范围。如果出现了这种情况,就可以用点运算来扩展感兴趣特征的对比度,使之占据可显示灰度级的更大范围。这一方法有时又被称为对比度扩展。

3)显示标定

  某些显示设备有特定的优选灰度范围,在这一范围内图像的视觉特征表现得最明显。如果用这样的设备显示图像,虽然图像中较暗和较亮的部位有相同的对比度,但显示时不能得到很好的表示。在这种情况下,可以利用点运算将所有的特征突出显示。此外,不少显示器不能保持像素的灰度值和屏幕上相应点的亮度间的线性关系,有的胶片记录仪不能线性地将灰度值转换为对应的密度值。出现上述情况时,可通过在显示或记录前设计合理的点运算算法加以克服。另外,还可以将点运算和显示的非线性组合起来,使它们互相抵消,得到图像显示的线性关系,这个过程被称为显示标定。

4)轮廓线

  利用点运算算法可以为图像加上轮廓线,例如用点运算进行图像的阈值化处理,根据图像的灰度等级把一幅图像划分成一些不连接的区域,这有助于确定图像中对象的边界或定义蒙版。蒙版是用来遮盖图层的,实际效果就是让图层变得透明。

5)裁剪

  数字图像通常以整数存储,因此可用的灰度分级范围总是有限的。对于8位的灰度图像,在存储每一像素值前,输出图像的灰度级一定要被裁剪到0~255的范围内。

2.灰度变换

2.1 灰度变换概述

  如果拍照时曝光不足或曝光过度,照片会显得灰朦朦的或者过白,如X光照片或陆地资源卫星多光谱图像。这实际上是因为对比度太小,且输入图像亮度分量的动态范围较小造成的。要改善这些图像的质量,可以采用灰度变换法,通过扩展输入图像的动态范围来达到图像增强的目的。

  在图像预处理中,图像的灰度变换是图像增强的重要手段。印刷图像在成像过程中经过传送和转换(如成像、复制、扫描、传输和显示等过程)后,经常会造成图像质量下降。通过采取适当的处理方法,可以把原本模糊不清甚至根本无法分辨的原始图片处理成

清楚、富含大量有用信息的可使用目标图像。因此,在医学、遥感、微生物、刑侦以及军

事等诸多科研和应用领域中,图像增强处理技术对原始图像的模式识别、目标检测等起着

重要作用。

  灰度变换主要利用点运算来修正像素灰度,由输入像素点的灰度值确定相应输出点的灰度值,是一种基于图像变换的操作。基于点运算的灰度变换可表示为:s=T®。其中T是灰度变换函数,r是变换前的灰度,s是变换后的像素。

2.2 灰度变换的作用

  图像灰度变换有以下作用:

(1)改善图像的质量,使图像能够显示更多的细节,提高图像的对比度(对比度拉

伸)。

(2)有选择地突出图像感兴趣的特征或者抑制图像中不需要的特征。

(3)可以有效地改变图像的直方图分布,使像素的分布更为均匀。

2.3 灰度变换的方法

  灰度变换函数描述了输入灰度值和输出灰度值之间变换关系,一旦灰度变换函数确定下来了,其输出的灰度值也就确定了。可见灰度变换函数的性质决定了灰度变换所能达到的效果。

  根据不同的应用要求,可以选择不同的变换函数,如正比函数和指数函数等。根据函数的性质,灰度变换的方法可以分为线性灰度变换、分段线性灰度变换、非线性灰度变换(包括对数函数变换和幂律函数变换(伽马变换))。

2.4 灰度化

  在具体讲述灰度变换之前,我们先了解一下灰度的概念。在数字图像中,像素是基本的表示单位,各个像素的亮暗程度用灰度值来标识。对于单色图像,它的每个像素的灰度值用0,255区间的整数表示,即图像分为256个灰度等级。

  对于彩色图像,它的每个像素都由R、G、B三个单色调配而成。如果每个像素的R、G、B完全相同,也就是R=G=B=D,该图像就是灰度图像,其中D被称为各个像素的灰度值。从理论上讲,等量的三基色R、G、B相加可以变为白色,其数学表达式为:

bash 复制代码
白色=(1×R)+(1×G)+(1×B)

  但是,由于人眼对R、G、B三个分量亮度的敏感度不一样,等量的R、G、B混合不能得到白色,故其混合比例需要调整。通常有3种方法对彩色图进行灰度化。

1)加权平均值法

  大量的实验数据表明,将0.299份红色、0.587份绿色、0.114份蓝色混合后可以得到白色,因此彩色图像可以根据以下公式变为灰度图像:

cpp 复制代码
D=0.299×R+0.587×G+0.114×B

  其中D表示点(x,y)转换后的灰度值,R、G、B为点(x,y)的3个单色分量。这个公式一般称为经验公式。

2)取最大值法

  最大值法是将彩色图像中的3个分量的亮度的最大值作为灰度图像的灰度值。

cpp 复制代码
D = max(R , G , B)

  取3个分量中的最大值作为灰度值,灰度处理首先读入图像的复制文件到内存中,找到R、G、B中的最大值,使颜色的分量值都相等且等于最大值,这样就可以将彩色图像变成灰度图像。

3)平均值法

  平均值法是对彩色图像中的3个分量的亮度值求平均值,从而得到一个灰度值,将其作为灰度图像的灰度:

cpp 复制代码
D = (R + G + B) /3

【例5.1】由经验公式实现RGB图像转灰度图像

  在代码中,通过imread和经验公式来实现将彩色图像转换为灰度图像。imread通过第二个参数的设置可以将读取的图像转为灰度图像。

cpp 复制代码
#include <iostream>
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

#pragma comment(lib, "opencv_world4140d.lib") //引用引入库

void grayImageShow(cv::Mat& input, cv::Mat& output)
{
	for (int i = 0; i < input.rows; ++i)
		for (int j = 0; j < input.cols; ++j)
			output.at<uchar>(i, j) = cv::saturate_cast<uchar>(0.114 * input.at<cv::Vec3b>(i, j)[0] + 0.587 * input.at<cv::Vec3b>(i, j)[1] + 0.2989 * input.at<cv::Vec3b>(i, j)[2]);
	cv::imshow("gray by experience", output);//由经验公式得到的灰度图像
}

int main(void)
{
	cv::Mat src, gray, dst;

	gray = cv::imread("1.jpg", cv::IMREAD_GRAYSCALE);//读取图像文件
	src = cv::imread("1.jpg");
	dst.create(src.rows, src.cols, CV_8UC1);

	cv::imshow("scr", src);
	cv::imshow("gray by imread", gray);//显示由imread得到的灰度图像
	grayImageShow(src, dst);//由经验公式得到的灰度图像
	waitKey(-1); //按键后再继续

	return 0;
}

【例5.2】优化后的RGB图像转灰度图像

cpp 复制代码
bool rgb2gray(unsigned char* src, unsigned char* dest, int width, int height)
{
	int r, g, b;
	for (int i = 0; i < width * height; ++i)
	{
		r = *src++; // load red
		g = *src++; // load green
		b = *src++; // load blue
		// build weighted average:
		*dest++ = (r * 76 + g * 150 + b * 30) >> 8;
	}
	return true;
}

int main()
{
	Mat src, gray, dst;
	src = cv::imread("1.jpg");
	dst.create(src.rows, src.cols, CV_8UC1);
	cv::imshow("scr", src);
	rgb2gray(src.data, dst.data, src.cols, src.rows);//由经验公式得到的灰度图像
	cv::imshow("gray by experience", dst);
	waitKey(-1); //按键后再继续
}

2.5 对比度

  前面提到了改善图像的质量,以及提高图像的对比度(对比度拉伸),那么什么是对比度呢?对比度就是画面的明亮部分和阴暗部分的灰度的比值。一幅图像的对比度越高,图像中被照物体的轮廓就越分明可见,图像也就越清晰;对比度越低,图像中的物体轮廓就越模糊,图像也就越不清晰。

  对比度对视觉效果的影响非常关键,一般来说对比度越大,图像越清晰醒目,色彩也越鲜明艳丽;对比度越小,则会让整个画面越灰蒙蒙的。高对比度对于图像的清晰度、细节表现、灰度层次表现都有很大帮助。在一些黑白反差较大的文本显示、CAD显示和黑白照片显示等方面,高对比度产品在黑白反差、清晰度、完整性等方面都具有优势。

  相对而言,在色彩层次方面,高对比度对图像的影响并不明显。对比度对于动态视频显示效果影响更大一些,因为动态图像中明暗转换比较快,对比度越高,人的眼睛越容易分辨出这样的转换过程。

相关推荐
chen_zn9540 分钟前
《VLA 系列》MemoryVLA++ | 感知-认知记忆 | 潜空间未来想象 | 论文与源码边界解析
人工智能·具身智能·vla
狂云歌40 分钟前
AI时代,学什么,怎么学
人工智能·学习
Allen_LVyingbo42 分钟前
医疗AI可扩展网格信息系统中网格计算技术的智能优化
大数据·人工智能·python·算法·机器学习·django·健康医疗
一个帅气昵称啊42 分钟前
.Net C# AI智能体开发-AI智能体
人工智能·c#·.net
MNLoser43 分钟前
AI agent开发——LangGraph接入持久化
linux·人工智能·windows·python
牛油果子哥q44 分钟前
C++序列式容器深度精讲:vector/list/deque底层实现、扩容原理、迭代器失效、性能对比、工程选型避坑
开发语言·c++·list
民乐团扒谱机1 小时前
【读论文】2005 一种旋律转录的分类方法A classification approach to melody transcription[C]
人工智能·分类·数据挖掘
程序员-李俞1 小时前
Coze 工作流调用异步 HTTP API 完整教程:任务 ID、循环轮询、状态判断与结果 URL 提取
网络·人工智能·网络协议·http·aigc·ai编程·ai写作
柠檬07111 小时前
图像亮暗不均匀,如何去除背景或者怎么处理可以让图像暗的地方亮一些,亮的地方暗一些
人工智能·opencv·计算机视觉