1. 程式人生 > >如何將jpg,bmp等普通圖片轉成層次分明的二值圖片(非僅用閾值分割)

如何將jpg,bmp等普通圖片轉成層次分明的二值圖片(非僅用閾值分割)

一,概述

一般,對圖片進行二值化時,我們會先進行灰度化,再進行閾值處理,既可以自己根據灰度圖片本身設定閾值,也可以根據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兩種畫素,需要靠黑畫素多少來造成明暗分佈的效果: