基礎ユニット2(イメージメディア) 第14回(2020/01/23)

関連サイトと資料

サンプル画像

canon7.jpg

house.png

forest.png

サンプルプログラム

createDCImage.py
import cv2
import numpy as np 
import os
	
# 3つの数の最小値を返します。
def min3(a, b, c):
    v = a
    if v > b:
        v = b
    
    if v > c:
        v = a
    
    return v
	
# (x, y)が画像をはみ出すか否かを判定します。
def isInside(x, y, w, h):
    if x < 0:
        return False
    if x >= w:
        return False
    if y < 0:
        return False
    if y >= h:
        return False
    
    return True
	
def createDCImage(img, para1):
    h, w, _ = img.shape
    img2 = np.zeros((h, w), np.uint8)
    for y in range(h):
        print(y)
        for x in range(w):
            v_min = [255, 255, 255]
            for yy in range(y-para1,y+para1+1):
                for xx in range(x-para1,x+para1+1):
                    if isInside(xx, yy, w, h) == True:
                        for i in range(3):
                            if v_min[i] > img[yy, xx, i]:
                                v_min[i] = img[yy, xx, i]
            
            img2[y, x] = min3(v_min[0], v_min[1], v_min[2])
    
    return img2
	
target = 'canon7.jpg'
ohm = 5
	
base, ext = os.path.splitext(target)
saveDCImageName = base + '_DC_{0}.png'.format(ohm)
	
orgImg = cv2.imread(target, cv2.IMREAD_COLOR)
dcImg = createDCImage(orgImg, ohm)
cv2.imwrite(saveDCImageName, dcImg)
	
cv2.imshow('Dark Channel', dcImg)
cv2.waitKey(0)
	
cv2.destroyAllWindows()

canon7_DC_5.png

estimateALColor.py
import cv2
import math
	
def estimateALColor(fog_img, dc_img):
    h, w = dc_img.shape
    total = w * h
    hist = cv2.calcHist([dc_img], [0], None, [256], [0, 256])
    th = -1
    sum = 0
    for i in range(255, -1, -1):
        sum += hist[i][0]
        if sum >= (total * 0.001):
            th = i
            break
    print('th = {0}'.format(th))
    
    v_max = 0
    r = -1
    g = -1
    b = -1
    for y in range(h):
        for x in range(w):
            if dc_img[y, x] >= th:
                bb, gg, rr = fog_img[y, x]
                bb, gg, rr = float(bb), float(gg), float(rr)
                bright = math.sqrt(bb * bb + gg * gg + rr * rr)
                if v_max < bright:
                    v_max = bright
                    b, g, r = fog_img[y, x]
    
    return r, g, b
	
target = 'canon7.jpg'
DC_filename = 'canon7_DC_5.png'
	
orgImg = cv2.imread(target, cv2.IMREAD_COLOR)
dcImg = cv2.imread(DC_filename, cv2.IMREAD_GRAYSCALE)
	
al_r, al_g, al_b = estimateALColor(orgImg, dcImg)
print('環境光: (r,g,b)=({0}, {1}, {2})'.format(al_r, al_g, al_b))

canon7.jpgから推定した環境光の色

estimateTMap.py
import cv2
import numpy as np 
import os
	
def min3(a, b, c):
    v = a
    if v > b:
        v = b
    
    if v > c:
        v = a
    
    return v
	
def isInside(x, y, w, h):
    if x < 0:
        return False
    if x >= w:
        return False
    if y < 0:
        return False
    if y >= h:
        return False
    
    return True
	
def createFineMap(fog_img):
    height, width, _ = fog_img.shape
    img2 = np.zeros((height, width), np.uint8)
	
    for y in range(height):
        for x in range(width):
            blue, green, red = fog_img[y, x]
            img2[y, x] = min3(blue, green, red)
    
    return img2
	
def saveAsJSON(tm, json_filename):
    height, width, _ = tm.shape
	
    fp = open(json_filename, 'w')
    fp.write("{\n")
    fp.write('   "width": {0}, "height": {1},\n'.format(width, height))
    for y in range(height):
        fp.write('   "row{0}": [ '.format(y))
        for x in range(width):
            if x < (width - 1):
                fp.write('{0},{1},{2},'.format(tm[y,x,0], tm[y,x,1], tm[y,x,2]))
            else:
                fp.write('{0},{1},{2} ]'.format(tm[y,x,0], tm[y,x,1], tm[y,x,2]))
        
        if y < (height - 1):
            fp.write(",\n")
        else:
            fp.write("\n")
    fp.write("}\n")
    fp.close()
	
def estimateTMap(fog_img, map_c, al_color, para1, para2):
    h, w = map_c.shape
    t = np.zeros((h, w, 3), np.float32)
    map_f = createFineMap(fog_img)
    map_t = np.zeros((h, w), np.uint8)
    for y in range(h):
        for x in range(w):
            v_max = 0
            for yy in range(y-para1+1,y+para1+1):
                for xx in range(x-para1,x+para1+1):
                    if isInside(xx, yy, w, h) == True:
                        if map_c[yy, xx] > v_max:
                            v_max = map_c[yy, xx]
            
            map_t[y, x] = v_max
            if v_max > map_f[y, x]:
                map_t[y, x] = map_f[y, x]
    
    for y in range(h):
        for x in range(w):
            for i in range(3):
                t[y, x, i] = 1 - para2 * map_t[y, x] / al_color[i]
    
    return t
	
target = 'canon7.jpg'
DC_filename = 'canon7_DC_5.png'
ohm = 5
al_r = 189
al_g = 190
al_b = 192
omega = 0.9
	
base, ext = os.path.splitext(target)
saveTMapJSONName = base + '_TM_{0}_{1:02d}.json'.format(ohm, int(omega*10))
	
orgImg = cv2.imread(target, cv2.IMREAD_COLOR)
coarseMap = cv2.imread(DC_filename, cv2.IMREAD_GRAYSCALE)
	
tMap = estimateTMap(orgImg, coarseMap, (al_b, al_g, al_r), ohm, omega)
saveAsJSON(tMap, saveTMapJSONName)

canon7.jpgから推定した透過マップ(canon7_TM_5_09.json)

clearFog.py
import cv2
import json
import numpy as np 
import os
	
def TMapfromJSON(json_filename):
    f = open(json_filename, 'r')
    jsonData = json.load(f)
    width = jsonData['width']
    height = jsonData['height']
    t_map = np.zeros((height, width, 3), np.float32)
	
    for y in range(height):
        list1 = jsonData['row{0}'.format(y)]
        for x in range(width):
            t_map[y, x, 0] = list1[x*3]
            t_map[y, x, 1] = list1[x*3 + 1]
            t_map[y, x, 2] = list1[x*3 + 2]
    f.close()
    return t_map
	
def createClearFogImage(fog_img, al_color, t_map, para1):
    関数の中身は各自で考える!
	
target = 'canon7.jpg'
tmap_json_filename = 'canon7_TM_5_09.json'
ohm = 5
al_r = 189
al_g = 190
al_b = 192
omega = 0.9
t0 = 0.01
	
base, ext = os.path.splitext(target)
saveClearedImageName = base + '_clear_{0}_{1:02d}.png'.format(ohm, int(omega*10))
	
orgImg = cv2.imread(target, cv2.IMREAD_COLOR)
tmap = TMapfromJSON(tmap_json_filename)
	
clearedImg = createClearFogImage(orgImg, (al_b, al_g, al_r), tmap, t0)
cv2.imwrite(saveClearedImageName, clearedImg)
	
cv2.imshow('Original Image', orgImg)
cv2.imshow('Clear Image', clearedImg)
cv2.waitKey(0)
	
cv2.destroyAllWindows()

canon7.jpgから推定した鮮明画像(canon7_clear_5_09.png)