如何将jpg,bmp等普通图片转成层次分明的二值图片(非仅用阈值分割)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qibofang/article/details/51510858

一,概述

一般,对图片进行二值化时,我们会先进行灰度化,再进行阈值处理,既可以自己根据灰度图片本身设置阈值,也可以根据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');

代码2:随机模板取值函数

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两种像素,需要靠黑像素多少来造成明暗分布的效果:




猜你喜欢

转载自blog.csdn.net/qibofang/article/details/51510858
今日推荐