这里我用到三种处理方法:直接相关运算,归一化相关系数,以及像素点个数统计。
轮胎图像直接作为模板,和汽车图像直接做相关运算,即用公式:
得到的矩阵不在像素值表示范围内,所以还要除以一个系数(height * width * 255)来确保能输出图像。
但这种方法得到的相关系数矩阵转化而来的图像效果并不明显,而且如果一片与检测图像无关的区域比较亮,也会使得该区域的相关系数值较大。
使用以下归一化相关系数矩阵的计算公式:
这样能得到一个元素范围在[-1, 1]的双精度浮点型矩阵,可以直接输出为图像。这次的效果明显好于上一次。
作归一化相关系数运算和直接作相关运算的对比:
前两种方法还不能找出我们需要的4个轮胎的坐标,而我希望能在对应于每个轮胎的范围内能唯一地识别出一个像素点,于是我自定义了一个函数CountingCorrelation。
假设当前遍历到原图的(i, j)处,如果模板上的一个像素点的值和对应的原图位置上的像素值相差不超过一定范围(例如我选定的是5,这个数经多次选择,觉得5较合适),那么就在给新的矩阵中的(i, j)处的值加1。
这样,和模板的像素值越接近的原图中的一片等大的区域的核心对应在新矩阵中的值就越大。然后用一定方法将新矩阵的每个元素取值都映射到[0, 255]中(这里我用的方法是cor(i, j) = exp(cor(i, j) / 8),用指数函数能使得大值与小值之间的差变得更大,更有利于使匹配的轮胎的位置更亮更明显,系数8则是经过多次选择觉得较合适的数)。
最后经过这样处理,恰巧能使4个像素的值为255,经过分析它们大致分别对于于原图4个轮胎的中心位置。
Correlation.m
function correlation = Correlation(img, template)
[h1,w1] = size(img);
[h2,w2] = size(template);
half_h = floor(h2 / 2);
half_w = floor(w2 / 2);
expand_img = zeros(h1 + h2 - 1, w1 + w2 - 1);
expand_img((half_h + 1):(h1 + half_h), (half_w + 1):(w1 + half_w)) = img;
expand_img = uint8(expand_img);
correlation = zeros(h1 + h2 - 1, w1 + w2 - 1);
for i = half_h + 1 : h1 + half_h
for j = half_w + 1 : w1 + half_w
for u = -half_h : half_h
for v = -half_w : half_w
correlation(i, j) = correlation(i, j) + double(expand_img(i + u, j + v)) * double(template(half_h + 1 + u, half_w + 1 + v));
end
end
end
end
correlation = correlation(half_h + 1 : h1 + half_h, half_w + 1 : w1 + half_w);
NormalizedCorrelation.m
function ncorr = NormalizedCorrelation(img, template)
[h1,w1] = size(img);
[h2,w2] = size(template);
avrg_template = mean2(template(:));
half_h = floor(h2 / 2);
half_w = floor(w2 / 2);
expand_img = zeros(h1 + h2 - 1, w1 + w2 - 1);
expand_img((half_h + 1):(h1 + half_h), (half_w + 1):(w1 + half_w)) = img;
expand_img = double(expand_img);
template = double(template);
ncorr = zeros(h1 + h2 - 1, w1 + w2 - 1);
for i = half_h + 1 : h1 + half_h
for j = half_w + 1 : w1 + half_w
numerator = 0;
denominator1 = 0;
denominator2 = 0;
avrg_img = mean2(expand_img(i - half_h : i + half_h, j - half_w : j + half_w));
for u = -half_h : half_h
for v = -half_w : half_w
numerator = numerator + (expand_img(i + u, j + v) - avrg_img) * (template(half_h + 1 + u, half_w + 1 + v) - avrg_template);
denominator1 = denominator1 + (template(half_h + 1 + u, half_w + 1 + v) - avrg_template) * (template(half_h + 1 + u, half_w + 1 + v) - avrg_template);
denominator2 = denominator2 + (expand_img(i + u, j + v) - avrg_img) * (expand_img(i + u, j + v) - avrg_img);
end
end
ncorr(i, j) = numerator / sqrt(denominator1 * denominator2);
end
end
ncorr = ncorr(half_h + 1 : h1 + half_h, half_w + 1 : w1 + half_w);
CountingCorrelation.m
function cor = CountingCorrelation(img, template)
[h1,w1] = size(img);
[h2,w2] = size(template);
half_h = floor(h2 / 2);
half_w = floor(w2 / 2);
expand_img = zeros(h1 + h2 - 1, w1 + w2 - 1);
expand_img((half_h + 1):(h1 + half_h), (half_w + 1):(w1 + half_w)) = img;
expand_img = uint8(expand_img);
cor = zeros(h1, w1);
for i = 1 : h1
for j = 1 : w1
for u = -half_h : half_h
for v = -half_w : half_w
if i + u < 1 || j + v < 1 || i + u > h1 || j + v > w1
continue;
elseif abs(int16(img(i + u, j + v)) - int16(template(half_h + 1 + u, half_w + 1 + v))) < 5
cor(i, j) = cor(i, j) + 1;
end
end
end
cor(i, j) = exp(cor(i, j) / 8);
end
end
cor = uint8(cor);
Task1.m
img = imread('car.png');
[h1,w1] = size(img);
template = imread('wheel.png');
[h2,w2] = size(template);
figure();
subplot(2, 2, 1);
imshow(img);
title('Original Image');
subplot(2, 2, 2);
ncorr = NormalizedCorrelation(img, template);
imshow(ncorr);
title('Normalized Correlation Image');
ccorr = CountingCorrelation(img, template);
subplot(2, 2, 3);
imshow(ccorr);
title('Counting Correlation');
correlation = Correlation(img, template);
correlation = correlation / (h2 * w2 * 255);
correlation = uint8(correlation);
subplot(2, 2, 4);
imshow(correlation);
title('Correlation Image');
num = 1;
lightest = zeros(4,2);
for i = 1 : h1
for j = 1 : w1
if ccorr(i, j) == 255
lightest(num,1) = i;
lightest(num,2) = j;
num = num + 1;
end
end
end
下图为图像检测效果图对比,
检测到的符合的像素点坐标: