Python / PIL / 画像をグレースケールにする、画像を2値化する

グレースケールにするときは
np.repeat()を使ってAllBrightness = [1,2,3]からAllRGB = [[1,1,1], [2,2,2], [3,3,3]] という排列を作ってImageオブジェクト化すればよい。

2値化するときは、たとえば閾値を100とするなら
AllRGB = [[1,2,3],[10,20,30],[100,200,250]]から[False,False,True]というマスク排列を作ってAllRGB = [[0,0,0],[0,0,0],[255,255,255]]という排列を作ってImageオブジェクト化すればよい。

from PIL import Image

import matplotlib.pyplot as plt
import numpy             as np

class IMAGE:
    def __init__(self, imgPath):
        self.srcImg = Image.open(imgPath)
        self.__initialize()
        
    def __initialize(self):
        self.srcArr        = np.asarray(self.srcImg)
        self.size          = self.srcArr.shape
        self.width         = self.size[1]
        self.height        = self.size[0]
        self.numOfPixels   = self.width * self.height
        self.AllRGB        = self.srcArr.reshape(self.numOfPixels, 3)
        self.AllBrightness = np.mean(self.AllRGB, axis=1, dtype="uint16")
        
    def showImg(self):
        plt.imshow(self.srcImg)
        plt.show()
        return self
        
    def showHist(self):
        plt.figure()
        plt.xlabel("brightness")
        plt.ylabel("freq")
        plt.hist(self.AllBrightness, range=(-0.5, 255.5), bins=256)
        plt.show()
        return self
    
    def changeBrightness(self, shift):
        rgb = self.AllRGB.astype(np.int16) + shift
        rgb = np.clip(rgb, 0, 255)
        rgb = rgb.reshape(self.height, self.width, 3)
        
        self.srcImg = Image.fromarray(rgb.astype(np.uint8))
        self.__initialize()
        return self    
    
    def conv2binary(self, threshold):
        larger  = self.AllBrightness>threshold
        smaller = ~larger
        
        self.AllRGB.flags.writeable = True
        self.AllRGB[larger]  = [255,255,255]
        self.AllRGB[smaller] = [0, 0, 0]
        
        self.AllRGB = self.AllRGB.reshape(self.height, self.width, 3)
        self.srcImg = Image.fromarray(self.AllRGB.astype(np.uint8))
        self.__initialize()
        return self
    
    def conv2gray(self):
        brt = np.repeat(self.AllBrightness, 3)
        brt = brt.reshape(self.height, self.width, 3)

        self.srcImg = Image.fromarray(brt.astype(np.uint8))
        self.__initialize()
        return self
        
    def export(self, filepath):
        self.srcImg.save(filepath)
        return self
    
########
# test #
########
if __name__ == "__main__":
    path = "H:\\img\\nanase6.png"
    
    img = IMAGE(path)
    img.showImg()
    img.showHist()
    
    img.conv2binary(50)
    img.showImg()
    img.showHist()

    img = IMAGE(path)
    img.conv2gray()
    img.showImg()
    img.showHist()

f:id:ti-nspire:20180805100934p:plain:h350 f:id:ti-nspire:20180805101008p:plain:h350 f:id:ti-nspire:20180805101031p:plain:h350

Python / PIL / 画像を明るくしたり暗くしたりする

PIL.Imageは画像の読み込み、生成、エクスポートに使うだけにして、あとはnumpyだけで処理する。

from PIL import Image

import matplotlib.pyplot as plt
import numpy             as np

class IMAGE:
    def __init__(self, imgPath):
        self.srcImg = Image.open(imgPath)
        self.__initialize()
        
    def __initialize(self):
        self.srcArr        = np.asarray(self.srcImg)
        self.size          = self.srcArr.shape
        self.width         = self.size[1]
        self.height        = self.size[0]
        self.numOfPixels   = self.width * self.height
        self.AllRGB        = self.srcArr.reshape(self.numOfPixels, 3)
        self.AllBrightness = np.mean(self.AllRGB, axis=1, dtype="uint16")
        
    def showImg(self):
        plt.imshow(self.srcImg)
        plt.show()
        return self
        
    def showHist(self):
        plt.figure()
        plt.xlabel("val")
        plt.ylabel("freq")
        plt.hist(self.AllBrightness, range=(-0.5, 255.5), bins=256)
        plt.show()
        return self
    
    def changeBrightness(self, shift):
        rgb = self.AllRGB.astype(np.int16) + shift
        rgb = np.clip(rgb, 0, 255)
        rgb = rgb.astype(np.uint8)
        rgb = rgb.reshape(self.height, self.width, 3)
        
        self.srcImg = Image.fromarray(rgb) # 新しいImageオブジェクトを生成して元のImageオブジェクトに上書きする。
        self.__initialize()
        return self    
        
    def export(self, filepath):
        self.srcImg.save(filepath)
        return self
    
########
# test #
########
if __name__ == "__main__":
    img = IMAGE("H:\\img\\fujiko.png") # 画像を読み込んで、
    img.showImg()
    img.showHist()

    img.changeBrightness(-150)           # 暗くしてみるが、
    img.showImg()                      # 単にただrgb値をずらしているだけなので元々暗かった部分は黒く潰れてしまう。
    img.showHist()
    
    img = IMAGE("H:\\img\\fujiko.png") # 今度はもう一度元の画像を読み込んで、
    img.changeBrightness(200)            # 明るくしてみるが、
    img.showImg()                      # 単にただrgb値をずらしているだけなので元々明るかった部分は白く飛んでしまう。
    img.showHist()
    
    img.export("H:\\img\\sute.png")

実行結果:
f:id:ti-nspire:20180804162626p:plain:h350 f:id:ti-nspire:20180804162700p:plain:h350 f:id:ti-nspire:20180804162721p:plain:h350