$C_w$取值范围分析
$$\begin{align}
C_w &=\frac{I-I_s}{I_s} \
&=\frac{I}{I_s} - 1.
\end{align}$$
设灰度最大值为$g_{max}$,那么$I$和$I_{s}$的范围都是$[0,g_{max}]$,因此$\frac{I}{I_{s} }$的范围为$[0,+\infty]$,那么$C_{w}$的范围为$[-1,+\infty]$。$C_{w}=0$表明$I=I_{s}$,即当前点和它周围的像素的某种均值完全一致;以$C_{w}=0$为界限,$C_{w}$小于$0$则表明当前点相比周围点的平均程度更暗;反之,$C_{w}$大于$0$则表示当前点比周围点更加亮。
$C_{w}$线性归一化可视化 可视化(归一化)
$$
C_{wview}=\frac{C_{w} }{C_{wmax}-C_{wmin} }\times g_{max}
$$
采用8位灰度时,$g_{max}$等于255。
以上线性归一化有误,因为有负值,所以上面这个公式永远不可能达到极值。因此直接把$C_{w}$线性放大然后叠加灰度加钳位的方法:
$$
C_{wview}=\max{0,\min{255,A\cdot C_{w}+\frac{g_{max} }{2}}}
$$
11/16今天突然意识到这个作业的所有滤波操作甚至卷积都是要自己手动实现的。。。所以现在开始先写卷积函数
高斯窗(高斯滤波器的生成)
由标准二维正态分布的函数表达式:
$$
f(x,y)=\frac{1}{2\pi \sigma^2}\exp \left[ -\frac{1}{2}\left( \frac{ {x^2+y^2} }{\sigma^2} \right) \right]
$$
平移到窗中心后,即得表达式。记窗的边长为$filterLength$,则需要平移的距离其实就是$filterLength$除以$2$向下取整,记为$d_{move}= \lfloor \frac{filterLength}{2} \rfloor$。所以高斯窗就是
$$
g(x,y)=f(x-d_{move},y-d_{move})=\frac{1}{2\pi \sigma^2}\exp \left[ -\frac{1}{2}\left( \frac{ {(x-d_{move})^2+(y-d_{move})^2} }{\sigma^2} \right) \right]
$$
AI说我自己写的卷积的时间复杂度是$$\text{复杂度} \approx O(\text{图像像素数} \times \text{卷积核像素数})$$
计算351窗宽时的计算量为3.6 亿亿次。
经过测试,自己写的卷积在计算窗宽351就算不动了,因此有些时候采用matlab的卷积函数conv2。
要求1:编程实现提取图像的Weber对比度,并设计对比度的可视化方法显示该对比度。显示手段视觉愉悦度越高越好。可以考虑在rgb分别计算后合成三通道显示,也可以在某个颜色空间仅操作强度通道。
提取方法已经在前面探讨过了,现在来探讨用什么方法来可视化显示更好。
我的代码们:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
|
function convResult = myConv(img, kernal)
kernalSize = size(kernal);
imgSize = size(img);
if length(imgSize) == 3
if imgSize(3) == 3
convResultr = myConv(img(:,:,1),kernal);
convResultg = myConv(img(:,:,2),kernal);
convResultb = myConv(img(:,:,3),kernal);
convResult(:,:,1) = convResultr;
convResult(:,:,2) = convResultg;
convResult(:,:,3) = convResultb;
return;
else
error('输入的图像的格式错误')
end
elseif length(imgSize) ~= 2
error('输入的图像的格式错误')
end
if length(kernalSize) ~= 2
error('卷积核必须是一个二维数组')
elseif kernalSize(1) ~= kernalSize(2)
error('卷积核的长和宽不相等')
elseif mod(kernalSize(1), 2) ~= 1
error('卷积核的边长不是奇数')
end
imgHeight = imgSize(1);
imgWidth = imgSize(2);
kernalLength = kernalSize(1);
padLength = idivide(kernalLength, uint32(2));
imgPad = zeros([imgHeight+2*padLength imgWidth+2*padLength], "double");
imgDouble = double(img);
imgPad(padLength+1:end-padLength, padLength+1:end-padLength) = imgDouble;
convResult = zeros([imgSize(1),imgSize(2)], "double");
for imgHeightIndex = 1:imgHeight
for imgWidthIndex = 1:imgWidth
convResult(imgHeightIndex,imgWidthIndex) = ...
sum(imgPad(imgHeightIndex:imgHeightIndex+kernalLength-1,...
imgWidthIndex:imgWidthIndex+kernalLength-1) .* kernal, "all");
end
end
end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| function filtResult = myFilter(img,filterType,filterLength,varargin)
if mod(filterLength, 2) ~= 1
error('滤波器的窗宽错误,只能为奇数')
end
if strcmpi(filterType, 'Average')
filtKernal = ones([filterLength filterLength], "double") ./ filterLength ^ 2;
elseif strcmpi(filterType, 'Gauss')
if isempty(varargin)
error('Gauss滤波器还需要一个sigma参数')
else
mySigma = varargin{1};
end
center = idivide(filterLength+1, int32(2));
[X,Y] = meshgrid(1:filterLength,1:filterLength);
X = X - double(center);
Y = Y - double(center);
filtKernal = 1/(2*pi*mySigma^2)*exp(-1/2*((X.^2+Y.^2)/mySigma^2));
filtKernal = filtKernal ./ sum(filtKernal, "all");
else
error('滤波器类型错误');
end
filtResult = conv2(img, filtKernal, "same");
end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| function img_weber = myWeber(img, filter_type, filter_size, varargin)
if strcmpi(filter_type, 'Gauss')
if isempty(varargin)
error('Gauss滤波还需要一个sigma参数')
else
sigma = varargin{1};
end
img_s = myFilter(img, filter_type, filter_size, sigma);
elseif strcmpi(filter_type, 'Average')
img_s = myFilter(img, filter_type, filter_size);
else
error('未知的滤波类型')
end
img_weber = (double(img) - img_s) ./ img_s;
|