画像二値化

ithat.me
このサイトを参考にしてPythonで実装した.
PILでGlayScaleにする方法はあるそうだが今回は敢えて使わずに実装した.

#coding:utf-8

from PIL import Image
from PIL import ImageDraw
from random import randint
from os.path import exists
from os import mkdir
from math import fabs
from random import random
from copy import deepcopy
from math import log

def drawPicture(Pic,size,result_file_path,result_file_name,sigma):
    im = Image.new("RGB",size)
    x_size = len(Pic[0])
    y_size = len(Pic[1])
    for x in range(x_size):
        for y in range(y_size):
            im.putpixel((x,y),Pic[x][y])
    if not exists(result_file_path):
        mkdir(result_file_path)
    result_file_name+="sigma_"+str(sigma)
    im.save(result_file_path+result_file_name,"PPM")
    del im


def main():
    #環境変数
    file_name = "Mandrill1.ppm"
    sigma     = int()
    result_file_path = "./binarizatino/result2/"
    result_file_name = ""

    #画像の読み込み
    print("original picture name:",file_name)
    im = Image.open(file_name)

    #RGBに変換
    rgb_im = im.convert('RGB')

    #画像サイズを取得
    size = rgb_im.size#(x:size[0],y:size[1])
    print("original picture size:",size)
    
    #画像のピクセルデータ
    Original = [[0 for _ in range(size[1])] for __ in range(size[0])]
    Original_luminance = [[0 for _ in range(size[1])] for __ in range(size[0])]
    Result   = [[0 for _ in range(size[1])] for __ in range(size[0])]
    Histgram = [0 for _ in range(256)]

    #オリジナル画像のピクセルRGBをリストOriginalに格納
    for x in range(size[0]):
        for y in range(size[1]):
            r,g,b = rgb_im.getpixel((x,y))#ピクセルを取得
            Original[x][y] = (r,g,b)

    #simple binarization
    white = (255,255,255)
    black = (0,0,0)
    sigma1 = float()
    sigma2 = float()
    n1 = int()
    n2 = int()

    for x in range(size[0]):
        for y in range(size[1]):
            luminance = 0.299*Original[x][y][0]+0.587*Original[x][y][1]+0.114*Original[x][y][2]#輝度 := 0.299×R + 0.587×G + 0.114×B (≒ 0.3R+0.6G+0.1B)
            Original_luminance[x][y] = luminance            
            Histgram[int(luminance)]+=1

    INF = 1e8
    res_max = -INF
    res_t   = -INF
    for t in range(256):
        w1 = 0 #クラス1の画素数
        w2 = 0
        s1 = 0
        s2 = 0
        m1 = 0
        m2 = 0
        for i in range(t):#class 1
            w1 += Histgram[i]
            s1 += Histgram[i]*i**2#gaso * (kido - heikin_kido)
        for i in range(t,256):#class 2
            w2 += Histgram[i]
            s2 += Histgram[i]*i**2

        if w1>0:
            m1 = s1/w1

        if w2>0:
            m2 = s2/w2

        tmp = w1*w2*(m1-m2)**2
        if tmp>res_max:
            res_max = tmp
            res_t = t

    print("best t : ",res_t)
    for x in range(size[0]):
        for y in range(size[1]):
            luminance = 0.299*Original[x][y][0]+0.587*Original[x][y][1]+0.114*Original[x][y][2]#輝度 := 0.299×R + 0.587×G + 0.114×B (≒ 0.3R+0.6G+0.1B)
            if luminance < res_t:
                Result[x][y]=black
            else:
                Result[x][y]=white
    drawPicture(Result,size,result_file_path,result_file_name,sigma)
                


if __name__ == "__main__":
    main()

元の画像
f:id:umashika5555:20170309210122p:plain
生成された画像
f:id:umashika5555:20170309210137p:plain