OpenCV3视觉对比敏感度(CSF)

目录

人类视觉系统特性

对比敏感度函数

基于CSF模型的滤波


人类视觉系统特性

经过生物学家和心理学家长期的探索和研究,通过结合生物学、心理学和简单的人眼视觉模型等理论,发现人类视觉系统(Human Visual System,HVS)的视觉感知与人的心理反应具有紧密联系。由于客观图像质量评价的最终目的是设计出一种评估结果与人类感知高度吻合的数学模型,因而,人类视觉心理学特性的引入具有举足轻重的作用。

  • 多通道分解特性

视觉皮层对不同类型的视觉信息有着各不相同的敏感性。人的视觉感知是一个多通道协同工作的过程,每个通道处理不同的视觉激励,通过相互联系以获得最佳的视觉效果。鉴于各通道的带通性,可以设计一组多尺度多方向的带通滤波器来近似模拟视觉感知的多分辨特性,对输入的视觉信息先在不同的频率和方向上进行分解,然后分配到相应的处理通道。如小波变换、Gabor变换和DCT变换等,已经被广泛应用于图像处理技术中。图像的高频部分表征视觉信息的边缘和结构特征;中频信息最易被区分,从而形成视觉关注点;低频部分提供细节较多的纹理信息。

  • 掩膜效应

HVS在感知时接收到的刺激往往不止一种,而是多种刺激相互作用、彼此联系和互相影响的综合过程。当多种视觉激励信号在空间或时间上同时作用于视觉系统,一种视觉激励信号的出现会削弱或增强其他一种或多种激励的响应,这种现象就是视觉掩膜效应(Visual Masking Effects)。掩膜效应在视觉观察中最典型的现象是,图像中平滑区域的失真由于背景参照物的对比度低而易于发觉,复杂纹理区域的失真因为背景参考物对比度高而不易发现。

  • 亮度特性

相较于激励的绝对亮度,HVS对激励与参照物之间亮度相对差异的敏感性更强。这个特性被称之为对比度,通常有两种基本定义方法:Weber-Fechner 定律和 Michelson 定律。Michelson 定律的表达式为C_{M}=\frac{L_{max}-L_{min}}{L_{max}+L_{min}},其中,L_{max}L_{min}分别表示图像中的最大和最小亮度。由Weber-Fechner定律表达式可推导出主观亮度与客观亮度的关系为S_n=k\textup{\textrm{ln}}B+k_0,表明主观感知亮度同客观亮度对数相关。
 

对比敏感度函数

对比敏感度函数(CSF)可以衡量HVS对各种视觉刺激频率的敏感性。它反映了在不同的空间频率上,人眼对目标亮度的辨别力不同。

CSF示意图

从频域来看,CSF对空间频率的不同成分具有不同的敏感程度。在低频区域和高频区域的视觉感知敏感度明显下降。具体表现为人眼对于图像中表征中频信息的边缘、轮廓和结构部分更加感兴趣,对于低频的平滑区域和纹理区域的敏感性较弱。一种经典的CSF由Campbell F. W.定义为H_1(f)=2.6\times (0.192+0.114\times f)\times \textup{exp}(-(0.114\times f)^{1.1}),其中,f=\sqrt{f_x^2+f_y^2} 为空间频率,f_xf_y为水平方向的空间频率和垂直方向的空间频率。另一种由Mannos和Sakrison提出,并由Daly改进的CSF模型如下:

其中 f 为径向空间频率,单位是(c / deg);θ∈[-π,π]表示角频率;λ=0.114;f_\theta = \frac{f}{0.15\textup{cos}(4\theta)+0.85}表示f的基于方向的修改,用来降低沿对角线方向的对比敏感度;H2(f,θ)是CSF模型的频率响应。

基于CSF模型的滤波

网上说CSF原理的很多,但是几乎没有完整实现代码。我搜了一下发现CSF模型的实现代码很少,最后只找到了建立后一种CSF模型(Mannos和Sakrison)的一段Matlab版本例子。这里我在VS2019+OpenCV3把它翻译成C++。

  • 计算公式中的径向频率
const int x = in.rows;
const int y = in.cols;
const double nfreq = 32.0;
Mat gker = (Mat_<double>(7, 7) <<
	0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,
	0.0000, 0.0000, 0.0000, 0.0002, 0.0000, 0.0000, 0.0000,
	0.0000, 0.0000, 0.0113, 0.0837, 0.0113, 0.0000, 0.0000,
	0.0000, 0.0002, 0.0837, 0.6187, 0.0837, 0.0002, 0.0000,
	0.0000, 0.0000, 0.0113, 0.0837, 0.0113, 0.0000, 0.0000,
	0.0000, 0.0000, 0.0000, 0.0002, 0.0000, 0.0000, 0.0000,
	0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000);
Mat xplane(y, x, CV_64FC1);
Mat yplane(y, x, CV_64FC1);
Mat xplane0(y, x, CV_64FC1);
Mat yplane0(y, x, CV_64FC1);
Mat radfreq(y, x, CV_64FC1);
double xb = -x / 2.0 + 0.5, xe = x / 2 - 0.5, yb = -y / 2.0 + 0.5, ye = y / 2.0 - 0.5;
meshgrid(xplane, yplane, xb, xe, yb, ye);
xplane = xplane / y * 2 * nfreq;
yplane = yplane / y * 2 * nfreq;
xplane0 = xplane.clone();
yplane0 = yplane.clone();
multiply(xplane, xplane, xplane);
multiply(yplane, yplane, yplane);
for (int i = 0; i < y; i++)
	for (int j = 0; j < x; j++)
		radfreq.ptr<double>(i)[j] = sqrt(xplane.ptr<double>(i)[j] + yplane.ptr<double>(i)[j]); // radial frequency

  • 计算CSF,结果H_{CSF}(u,v)表示基于DFT的H_2(f,\theta ),其中u和v是DFT坐标
Mat angleplane(y, x, CV_64FC1);
Mat ICFfrq;
Mat csf(y, x, CV_64FC1);
Mat ICFcx(x, y, CV_64FC2);
double w = 0.7;
	for (int i = 0; i < y; i++)
		for (int j = 0; j < x; j++)
			angleplane.ptr<double>(i)[j] = atan2(yplane0.ptr<double>(i)[j], xplane0.ptr<double>(i)[j]);
angleplane *= 4;
for (int i = 0; i < y; i++)
	for (int j = 0; j < x; j++)
		angleplane.ptr<double>(i)[j] = cos(angleplane.ptr<double>(i)[j]);
angleplane = (1 - w) / 2 * angleplane;
for (int i = 0; i < y; i++)
	for (int j = 0; j < x; j++)
		angleplane.ptr<double>(i)[j] += (1 + w) / 2;
divide(radfreq, angleplane, radfreq);
xplane = radfreq * 0.114;
yplane = xplane.clone();
for (int i = 0; i < y; i++)
	for (int j = 0; j < x; j++)
		xplane.ptr<double>(i)[j] += 0.0192;
xplane *= 2.6;
for (int i = 0; i < y; i++) {
	for (int j = 0; j < x; j++) {
		yplane.ptr<double>(i)[j] = pow(yplane.ptr<double>(i)[j], 1.1);
		yplane.ptr<double>(i)[j] = -yplane.ptr<double>(i)[j];
		yplane.ptr<double>(i)[j] = exp(yplane.ptr<double>(i)[j]);
	}
}
multiply(xplane, yplane, angleplane);
std::vector<std::pair<int, int> > p;
for (int i = 0; i < y; i++)
	for (int j = 0; j < x; j++)
		if (radfreq.ptr<double>(i)[j] < 7.8909)
			p.push_back(std::make_pair(i, j));
for (auto iter = p.cbegin(); iter != p.cend(); iter++)
	angleplane.ptr<double>(iter->first)[iter->second] = 0.9809;
csf = angleplane.t();
for (int i = 0; i < csf.rows; i++)
	for (int j = 0; j < csf.cols; j++)
		csf.ptr<double>(i)[j] = floor(csf.ptr<double>(i)[j] * 10000.0 + 0.5) / 10000.0;

  • 通过I_{CF}=f^{-1}(H_{CSF}(u,v)f(I))在频域中执行CSF滤波,其中f(·)和其反函数分别表示DFT和IDFT。生成的滤波后图像为I_{CF},滤波后采用上面的7×7的σ=0.5高斯核gker对I_{CF}滤波,最后把I_{CF}归一化从而能够显示出来。
ICFfrq = fft2(in);
ICFfrq = fftshift(ICFfrq);
std::vector<Mat> csfv;
split(ICFfrq, csfv);
multiply(csfv[0], csf, csfv[0]);
multiply(csfv[1], csf, csfv[1]);
merge(csfv, ICFfrq);
ICFfrq = ifftshift(ICFfrq);
ICFcx = ifft2(ICFfrq);
Mat ICF = ireal(ICFcx); // 取实部
filter2D(ICF, ICF, CV_64FC1, gker); // 可选的滤波
// return ICF;

 

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
### 回答1: OpencvSharp 是开源的计算机视觉领域的 C#语言封装库,可以用于图像处理、图像分析、模式识别等领域。扫描图片对比度是图像处理的一个重要应用之一。对比度是指图像中明暗色调变化的大小,即图像中最亮与最暗像素的强度之差。对比度越大,图像中暗部越暗,亮部越亮,反之对比度越小,图像中暗部越明亮,亮部越暗。下面我们来了解 OpencvSharp 如何扫描图片对比度。 OpencvSharp 中提供了很多用于计算对比度的函数,其中最常用的是 cv::equalizeHist 函数。该函数会将输入图像的直方图均衡化,从而增加图像的对比度。具体使用方法如下: 1. 载入图像:Mat img = Cv2.ImRead("image.jpg"); 2. 转为灰度图像:Mat grayImg = new Mat(); Cv2.CvtColor(img, grayImg, ColorConversionCodes.BGR2GRAY); 3. 直方图均衡化:Mat histImg = new Mat(); Cv2.EqualizeHist(grayImg, histImg); 4. 显示图像:Cv2.ImShow("Histogram Equalization", histImg); 通过上述方法,就可以扫描图片对比度并对其进行处理。此外,还可以通过调整对比度参数,更加精细地控制图像的对比度。 ### 回答2: OpenCVSharp是一个C#语言的开源计算机视觉库,它提供了许多图像处理和计算机视觉相关的函数和工具。扫描图像的对比度是一个常见的图像处理需求,OpenCVSharp提供了几种不同的方法来检测和增强图像的对比度。 一种简单的方法是使用直方图均衡化方法。它通过重新分配图像像素值来增强图像的对比度。OpenCVSharp提供了一个名为EqualizeHist的函数,可以用于执行直方图均衡化操作。 另一种更复杂的方法是使用自适应直方图均衡化方法来增强图像的对比度。这种方法是在局部图像块上执行直方图均衡化操作,以保留图像的局部对比度和细节。OpenCVSharp还提供了一个名为CLAHE的函数,可以用于执行自适应直方图均衡化操作。 除了直方图均衡化方法外,还可以使用一些其他的算法和技术来增强图像的对比度,如增强锐度、彩色平衡等。无论采用何种方法,都需要根据具体应用场景选择最合适的算法和参数,以获得最佳的对比度增强效果。 ### 回答3: OpenCvSharp是一个开源计算机视觉库,用于处理图像和视频的编程库,它提供了丰富的图像处理功能,包括的对比度调整。要用OpenCvSharp扫图片对比度,首先需要加载图像,最好是以灰度方式加载,以便更方便地进行对比度调整。然后可以使用equalizeHist()函数对图像进行直方图均衡化来增加对比度。该函数将把灰度图片的像素值分布均衡化到较宽的像素值范围内,进而增加图像的对比度。要调整对比度的范围,可以使用convertScaleAbs()函数来调整图像的亮度和对比度值。使用类似于“Mat dst = src⋅alpha+beta”的公式,可以调整对比度和亮度值。在该公式中,alpha和beta是任选参数,用于调整对比度和亮度,src是源图像,dst是目标图像。除此之外,还可以使用Matplotlib库来可视化图像和对比度的变化,并评估调整结果。OpenCvSharp的函数和类库非常清晰和易于使用,可以根据需要选择合适的函数和方法进行图像对比度调整。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值