一,概述
一般,对图片进行二值化时,我们会先进行灰度化,再进行阈值处理,既可以自己根据灰度图片本身设置阈值,也可以根据graythresh函数自动确定阈值,如下:
I = imread('input1.jpg'); [h, w, src] = size(I); if src == 3 I = rgb2gray(I); end a = 160; %I = I > a; I = im2bw(I, graythresh(I) * 0.9); imshow(I);imwrite(I, 'test.jpg');
原图 阈值确定的二值图 层次分明的二值图
二,算法思路
由于二值图中的像素要么是0,要么是1,因此我们不能依靠色阶来产生二值图层次分明的效果,我们只能使较暗的地方像素多些,较亮的地方像素少些,因此本文采用了模板的方法,通过原图与模板进行像素大小的比较,根据概率高低可以保证较暗的地方像素多,较亮的地方像素少。算法的大致思路分为以下几个部分:
1),本文采用了4*4的模板,因此需要将原图尺寸的大小扩充至4的整数倍,为保证原图尽量不被拉伸,若原图的高为w,宽为h,则设置新的高W = floor(w / 4.0) + 1,
H = floor(h / 4.0) + 1;
2),设置模板,若将原图片以4*4的小矩阵为单位进行分割,如下,之后再对每个小矩阵分别与模板进行比较。为了保证图片效果的随机性,每次进行比较的模板都应该具备随机性。
对于模板的设置,可以先使template = 1: 16,然后利用随机数rand(1)随机打乱,最后再变形成矩阵,由于灰度值的范围为0~255,因此最后对模板的每个像素都应乘以16或者15,才能保证随机性。
3),上一步基本上能将原图的效果显示出来,但可能由于随机性的关系造成了轮廓有些不清晰,因此需要从原始灰度图中提供轮廓,再与上一步生成的二值图进行或操作。
三,具体代码
程序如下,太部分语句比较基础,就不细述了,其中代码1是根据上述算法流程写的,代码2为调用的随机模板:
注意的地方:使用rand(1)函数时,即使round(rand(1)*16),最后的整数结果可能为0,而matlab中的下标都是从1开始,因此需要重新取随机值。
代码1:
clear; clc; %读入原图灰度化 I = imread('input1.jpg'); [h, w, src] = size(I); if src == 3 I = rgb2gray(I); end figure, subplot(211), imshow(I), title('原始灰度图像'); subplot(212), plot(imhist(I)/(h*w)), title('直方图'); %imshow(I), title('原始灰度图像'); %扩展图像高和宽为4K, K为整数 a = 4.0; k1 = floor(h / a) + 1; k2 = floor(w / a) + 1; M = k1 * a; N = k2 * a; I = imresize(I, [M, N]); figure, imshow(I), title('4的整数倍图像灰度图像'); %利用随机模板生成二值化图 I_er = zeros(M, N); for i = 1: a: M for j = 1: a: N newTemplate = RandomTemplate(); I_er(i: i+a-1, j: j+a-1) = I(i: i+a-1, j: j+a-1) > newTemplate; end end %随机模板造成轮廓不清晰,需要|原来的轮廓 I = im2double(I); imX = [abs(I(:,1:(end-1)) - I(:,2:end)), zeros(M, 1)];%最右边增加一列0 imY = [abs(I(1:(end-1),:) - I(2:end,:)); zeros(1, N)];%最下边增加一行0 imX = imX .^ 2; imY = imY .^ 2; imEdge = sqrt(imX + imY); imEdge = immultiply(imEdge, 5); imEdge = imEdge .^ 50;%次数越多,数值越低,黑色像素越少 imEdge = uint8(imEdge .* 255); imEdge = im2bw(imEdge, graythresh(imEdge)*0.4); figure, imshow(imEdge); figure, imshow(I_er), title('二值图像I_er'); imwrite(I_er, 'shili.bmp'); I_er1 = ~(~I_er | imEdge); figure, imshow(I_er1), title('二值图像I_er1'); imwrite(I_er1, 'shili1.bmp');
function newTemplate = RandomTemplate() newTemplate = 1: 16; %将数字1,2...16随机放在newTemplate中,根据rand进行16次置换 for i = 1: 16 num = round(rand(1)*16); while num == 0 num = round(rand(1)*16); end temp = newTemplate(i); newTemplate(i) = newTemplate(num); newTemplate(num) = temp; end newTemplate = 15 * reshape(newTemplate, 4, 4);%16时黑点过多,效果不好 end
原始图 模板生成的二值图
说明:
如果将图片放大的话,我们能看到如下的图,这是因为二值图只有0和1两种像素,需要靠黑像素多少来造成明暗分布的效果: