From de8a39669e1b6cbb2706e3025699f6fcd30e9faa Mon Sep 17 00:00:00 2001 From: yoyoyo-yo Date: Wed, 28 Aug 2019 07:14:28 +0900 Subject: [PATCH] add --- Question_51_60/README.md | 4 +- Question_51_60/answers/answer_51.jpg | Bin 14645 -> 14462 bytes Question_51_60/answers/answer_51.py | 158 ++++++++++++++++---------- Question_51_60/answers/answer_52.jpg | Bin 10812 -> 10963 bytes Question_51_60/answers/answer_52.py | 158 ++++++++++++++++---------- Question_51_60/answers/answer_53.jpg | Bin 10963 -> 14352 bytes Question_51_60/answers/answer_53.py | 161 +++++++++++++++++---------- Question_51_60/answers/answer_54.py | 55 ++++++--- Question_51_60/answers/answer_55.py | 54 ++++++--- Question_51_60/answers/answer_56.py | 57 ++++++---- Question_51_60/answers/answer_57.jpg | Bin 11067 -> 11039 bytes Question_51_60/answers/answer_57.py | 70 ++++++++---- Question_51_60/answers/answer_58.py | 117 +++++++++++-------- Question_51_60/answers/answer_59.py | 122 +++++++++++--------- Question_51_60/answers/answer_60.py | 14 ++- README.md | 3 +- 16 files changed, 622 insertions(+), 351 deletions(-) diff --git a/Question_51_60/README.md b/Question_51_60/README.md index 88ef330d..1ef42d80 100644 --- a/Question_51_60/README.md +++ b/Question_51_60/README.md @@ -120,7 +120,7 @@ NCCは照明変化に強いと言われる。 ZNCC(Zero means Normalized Cross Correlation)とは零平均正規化相互相関を類似度にする手法であり、Sが**最大**の位置がマッチング位置となる。 -画像Iの平均値をmi、画像Tの平均値をmtとすると、Sは次式で計算される。 +画像Iの平均値をmi、画像Tの平均値をmtとすると、Sは次式で計算される。(ただし、平均値はRGB成分ごとに減算する) ```bash Sum_{x=0:w, y=0:h} (I(i+x, j+y)-mi) * (T(x, y)-mt) @@ -129,7 +129,7 @@ S = ---------------------------------------------------------------------------- ``` このSは、-1<=S<=1をとる。 -ZNCCは平均値を引くことでNCCよりも照明変化に強いと言われる。(だが今回は検出が失敗する。) +ZNCCは平均値を引くことでNCCよりも照明変化に強いと言われる。 |入力 (imori.jpg) |テンプレート画像(imori_part.jpg)|出力(answers/answer_57.jpg)| |:---:|:---:|:---:| diff --git a/Question_51_60/answers/answer_51.jpg b/Question_51_60/answers/answer_51.jpg index 49869381e7ca9bc94fe10263f0172ca70f89d7fe..306e78bde8e435ebb6808b5ace882eb402cb7f1f 100644 GIT binary patch literal 14462 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


qxki0;% zL3h;Y*5rw;@z}m6dUO| f)6=q4<2|9cSLtoF#}3*0FDLRZ-5g_vtd9I2`d(CJ literal 14645 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 P=z9Nv`&bQOdG!APhZe)d diff --git a/Question_51_60/answers/answer_51.py b/Question_51_60/answers/answer_51.py index 7381769b..ce1a5dbc 100644 --- a/Question_51_60/answers/answer_51.py +++ b/Question_51_60/answers/answer_51.py @@ -2,65 +2,109 @@ import numpy as np import matplotlib.pyplot as plt + +# Gray scale +def BGR2GRAY(img): + b = img[:, :, 0].copy() + g = img[:, :, 1].copy() + r = img[:, :, 2].copy() + + # Gray scale + out = 0.2126 * r + 0.7152 * g + 0.0722 * b + out = out.astype(np.uint8) + + return out + +# Otsu Binalization +def otsu_binarization(img, th=128): + H, W = img.shape + out = img.copy() + + max_sigma = 0 + max_t = 0 + + # determine threshold + for _t in range(1, 255): + v0 = out[np.where(out < _t)] + m0 = np.mean(v0) if len(v0) > 0 else 0. + w0 = len(v0) / (H * W) + v1 = out[np.where(out >= _t)] + m1 = np.mean(v1) if len(v1) > 0 else 0. + w1 = len(v1) / (H * W) + sigma = w0 * w1 * ((m0 - m1) ** 2) + if sigma > max_sigma: + max_sigma = sigma + max_t = _t + + # Binarization + print("threshold >>", max_t) + th = max_t + out[out < th] = 0 + out[out >= th] = 255 + + return out + + +# Erosion +def Erode(img, Erode_time=1): + H, W = img.shape + out = img.copy() + + # kernel + MF = np.array(((0, 1, 0), + (1, 0, 1), + (0, 1, 0)), dtype=np.int) + + # each erode + for i in range(Erode_time): + tmp = np.pad(out, (1, 1), 'edge') + # erode + for y in range(1, H+1): + for x in range(1, W+1): + if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4: + out[y-1, x-1] = 0 + + return out + + +# Dilation +def Dilate(img, Dil_time=1): + H, W = img.shape + + # kernel + MF = np.array(((0, 1, 0), + (1, 0, 1), + (0, 1, 0)), dtype=np.int) + + # each dilate time + out = img.copy() + for i in range(Dil_time): + tmp = np.pad(out, (1, 1), 'edge') + for y in range(1, H+1): + for x in range(1, W+1): + if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) >= 255: + out[y-1, x-1] = 255 + + return out + + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape - -# Otsu binary -## Grayscale -out = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0] -out = out.astype(np.uint8) - -## Determine threshold of Otsu's binarization -max_sigma = 0 -max_t = 0 - -for _t in range(1, 255): - v0 = out[np.where(out < _t)[0]] - m0 = np.mean(v0) if len(v0) > 0 else 0. - w0 = len(v0) / (H * W) - v1 = out[np.where(out >= _t)[0]] - m1 = np.mean(v1) if len(v1) > 0 else 0. - w1 = len(v1) / (H * W) - sigma = w0 * w1 * ((m0 - m1) ** 2) - if sigma > max_sigma: - max_sigma = sigma - max_t = _t - -## Binarization -#print("threshold >>", max_t) -th = max_t -out[out < th] = 0 -out[out >= th] = 255 - -# Morphology filter -MF = np.array(((0, 1, 0), - (1, 0, 1), - (0, 1, 0)), dtype=np.int) - -# Morphology - erode -Erode_time = 1 -erode = out.copy() - -for i in range(Erode_time): - tmp = np.pad(out, (1, 1), 'edge') - for y in range(1, H+1): - for x in range(1, W+1): - if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4: - erode[y-1, x-1] = 0 - -# Morphology - dilate -Dil_time = 1 -dilate = out.copy() - -for i in range(Dil_time): - tmp = np.pad(out, (1, 1), 'edge') - for y in range(1, H+1): - for x in range(1, W+1): - if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) >= 255: - dilate[y-1, x-1] = 255 - -out = np.abs(erode - dilate) * 255 + +# Grayscale +gray = BGR2GRAY(img) + +# Otsu's binarization +otsu = otsu_binarization(gray) + +# Erode image +eroded = Erode(otsu) + +# Delate image +dilated = Dilate(otsu) + +# Morphology +out = np.abs(eroded - dilated) * 255 # Save result cv2.imwrite("out.jpg", out) diff --git a/Question_51_60/answers/answer_52.jpg b/Question_51_60/answers/answer_52.jpg index 9aa5af63485ee64e80f3006dbc9685ba76dd5d2a..073dc7341cb1861f617834aa0057fc82ed4920d6 100644 GIT binary patch delta 10675 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 delta 10523 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 diff --git a/Question_51_60/answers/answer_52.py b/Question_51_60/answers/answer_52.py index af52f43f..2d7fb2fa 100644 --- a/Question_51_60/answers/answer_52.py +++ b/Question_51_60/answers/answer_52.py @@ -2,64 +2,110 @@ import numpy as np import matplotlib.pyplot as plt +# Gray scale +def BGR2GRAY(img): + b = img[:, :, 0].copy() + g = img[:, :, 1].copy() + r = img[:, :, 2].copy() + + # Gray scale + out = 0.2126 * r + 0.7152 * g + 0.0722 * b + out = out.astype(np.uint8) + + return out + +# Otsu Binalization +def otsu_binarization(img, th=128): + H, W = img.shape + out = img.copy() + + max_sigma = 0 + max_t = 0 + + # determine threshold + for _t in range(1, 255): + v0 = out[np.where(out < _t)] + m0 = np.mean(v0) if len(v0) > 0 else 0. + w0 = len(v0) / (H * W) + v1 = out[np.where(out >= _t)] + m1 = np.mean(v1) if len(v1) > 0 else 0. + w1 = len(v1) / (H * W) + sigma = w0 * w1 * ((m0 - m1) ** 2) + if sigma > max_sigma: + max_sigma = sigma + max_t = _t + + # Binarization + print("threshold >>", max_t) + th = max_t + out[out < th] = 0 + out[out >= th] = 255 + + return out + + +# Erosion +def Erode(img, Erode_time=1): + H, W = img.shape + out = img.copy() + + # kernel + MF = np.array(((0, 1, 0), + (1, 0, 1), + (0, 1, 0)), dtype=np.int) + + # each erode + for i in range(Erode_time): + tmp = np.pad(out, (1, 1), 'edge') + # erode + for y in range(1, H+1): + for x in range(1, W+1): + if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4: + out[y-1, x-1] = 0 + + return out + + +# Dilation +def Dilate(img, Dil_time=1): + H, W = img.shape + + # kernel + MF = np.array(((0, 1, 0), + (1, 0, 1), + (0, 1, 0)), dtype=np.int) + + # each dilate time + out = img.copy() + for i in range(Dil_time): + tmp = np.pad(out, (1, 1), 'edge') + for y in range(1, H+1): + for x in range(1, W+1): + if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) >= 255: + out[y-1, x-1] = 255 + + return out + +# Opening morphology +def Morphology_Opening(img, time=1): + dil = Dilate(img, Dil_time=time) + erode = Erode(dil, Erode_time=time) + return erode + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape - -# Otsu binary -## Grayscale -out = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0] -out = out.astype(np.uint8) - -## Determine threshold of Otsu's binarization -max_sigma = 0 -max_t = 0 - -for _t in range(1, 255): - v0 = out[np.where(out < _t)] - m0 = np.mean(v0) if len(v0) > 0 else 0. - w0 = len(v0) / (H * W) - v1 = out[np.where(out >= _t)] - m1 = np.mean(v1) if len(v1) > 0 else 0. - w1 = len(v1) / (H * W) - sigma = w0 * w1 * ((m0 - m1) ** 2) - if sigma > max_sigma: - max_sigma = sigma - max_t = _t - -## Binarization -#print("threshold >>", max_t) -th = max_t -out[out < th] = 0 -out[out >= th] = 255 - -# Morphology filter -MF = np.array(((0, 1, 0), - (1, 0, 1), - (0, 1, 0)), dtype=np.int) - -# Morphology - erode -Erode_time = 3 -mor = out.copy() - -for i in range(Erode_time): - tmp = np.pad(mor, (1, 1), 'edge') - for y in range(1, H+1): - for x in range(1, W+1): - if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4: - mor[y-1, x-1] = 0 - -# Morphology - dilate -Dil_time = 3 - -for i in range(Dil_time): - tmp = np.pad(mor, (1, 1), 'edge') - for y in range(1, H+1): - for x in range(1, W+1): - if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) >= 255: - mor[y-1, x-1] = 255 - -out = out - mor + +# Grayscale +gray = BGR2GRAY(img) + +# Otsu's binarization +otsu = otsu_binarization(gray) + +# Opening process +opened = Morphology_Opening(otsu, time=3) + +# Tophat +out = np.abs(otsu - opened) * 255 # Save result cv2.imwrite("out.jpg", out) diff --git a/Question_51_60/answers/answer_53.jpg b/Question_51_60/answers/answer_53.jpg index 073dc7341cb1861f617834aa0057fc82ed4920d6..4129ba5d6a4374e25015928b98074f68f9007002 100644 GIT binary patch literal 14352 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 CCZmP` diff --git a/Question_51_60/answers/answer_53.py b/Question_51_60/answers/answer_53.py index 9b4d98c1..21d525fb 100644 --- a/Question_51_60/answers/answer_53.py +++ b/Question_51_60/answers/answer_53.py @@ -2,64 +2,113 @@ import numpy as np import matplotlib.pyplot as plt + +# Gray scale +def BGR2GRAY(img): + b = img[:, :, 0].copy() + g = img[:, :, 1].copy() + r = img[:, :, 2].copy() + + # Gray scale + out = 0.2126 * r + 0.7152 * g + 0.0722 * b + out = out.astype(np.uint8) + + return out + +# Otsu Binalization +def otsu_binarization(img, th=128): + H, W = img.shape + out = img.copy() + + max_sigma = 0 + max_t = 0 + + # determine threshold + for _t in range(1, 255): + v0 = out[np.where(out < _t)] + m0 = np.mean(v0) if len(v0) > 0 else 0. + w0 = len(v0) / (H * W) + v1 = out[np.where(out >= _t)] + m1 = np.mean(v1) if len(v1) > 0 else 0. + w1 = len(v1) / (H * W) + sigma = w0 * w1 * ((m0 - m1) ** 2) + if sigma > max_sigma: + max_sigma = sigma + max_t = _t + + # Binarization + print("threshold >>", max_t) + th = max_t + out[out < th] = 0 + out[out >= th] = 255 + + return out + + +# Erosion +def Erode(img, Erode_time=1): + H, W = img.shape + out = img.copy() + + # kernel + MF = np.array(((0, 1, 0), + (1, 0, 1), + (0, 1, 0)), dtype=np.int) + + # each erode + for i in range(Erode_time): + tmp = np.pad(out, (1, 1), 'edge') + # erode + for y in range(1, H+1): + for x in range(1, W+1): + if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4: + out[y-1, x-1] = 0 + + return out + + +# Dilation +def Dilate(img, Dil_time=1): + H, W = img.shape + + # kernel + MF = np.array(((0, 1, 0), + (1, 0, 1), + (0, 1, 0)), dtype=np.int) + + # each dilate time + out = img.copy() + for i in range(Dil_time): + tmp = np.pad(out, (1, 1), 'edge') + for y in range(1, H+1): + for x in range(1, W+1): + if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) >= 255: + out[y-1, x-1] = 255 + + return out + +# Closing morphology +def Morphology_Closing(img, time=1): + erode = Erode(img, Erode_time=time) + dil = Dilate(erode, Dil_time=time) + return erode + + + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape - -# Otsu binary -## Grayscale -out = 0.2126 * img[..., 2] + 0.7152 * img[..., 1] + 0.0722 * img[..., 0] -out = out.astype(np.uint8) - -## Determine threshold of Otsu's binarization -max_sigma = 0 -max_t = 0 - -for _t in range(1, 255): - v0 = out[np.where(out < _t)] - m0 = np.mean(v0) if len(v0) > 0 else 0. - w0 = len(v0) / (H * W) - v1 = out[np.where(out >= _t)] - m1 = np.mean(v1) if len(v1) > 0 else 0. - w1 = len(v1) / (H * W) - sigma = w0 * w1 * ((m0 - m1) ** 2) - if sigma > max_sigma: - max_sigma = sigma - max_t = _t - -## Binarization -#print("threshold >>", max_t) -th = max_t -out[out < th] = 0 -out[out >= th] = 255 - -# Morphology filter -MF = np.array(((0, 1, 0), - (1, 0, 1), - (0, 1, 0)), dtype=np.int) - -# Morphology - dilate -Dil_time = 3 -mor = out.copy() - -for i in range(Dil_time): - tmp = np.pad(mor, (1, 1), 'edge') - for y in range(1, H+1): - for x in range(1, W+1): - if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) >= 255: - mor[y-1, x-1] = 255 - -# Morphology - erode -Erode_time = 3 - -for i in range(Erode_time): - tmp = np.pad(mor, (1, 1), 'edge') - for y in range(1, H+1): - for x in range(1, W+1): - if np.sum(MF * tmp[y-1:y+2, x-1:x+2]) < 255*4: - mor[y-1, x-1] = 0 - -out = mor - out + +# Grayscale +gray = BGR2GRAY(img) + +# Otsu's binarization +otsu = otsu_binarization(gray) + +# Opening process +opened = Morphology_Closing(otsu, time=3) + +# Tophat +out = np.abs(opened - otsu) * 255 # Save result cv2.imwrite("out.jpg", out) diff --git a/Question_51_60/answers/answer_54.py b/Question_51_60/answers/answer_54.py index 73c06b32..37703725 100644 --- a/Question_51_60/answers/answer_54.py +++ b/Question_51_60/answers/answer_54.py @@ -2,28 +2,47 @@ import numpy as np import matplotlib.pyplot as plt + +# template matching +def Template_matching(img, template): + # get original image shape + H, W, C = img.shape + + # get template image shape + Ht, Wt, Ct = template.shape + + # Templete matching + # prepare x, y index + i, j = -1, -1 + # prepare evaluate value + v = 255 * H * W * C + + for y in range(H - Ht): + for x in range(W - Wt): + # get SSD value + _v = np.sum((img[y : y + Ht, x : x + Wt] - template) ** 2) + + # if SSD is min + if _v < v: + v = _v + i, j = x, y + + out = img.copy() + # draw rectangle + cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) + out = out.astype(np.uint8) + + return out + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape # Read templete image -temp = cv2.imread("imori_part.jpg").astype(np.float32) -Ht, Wt, Ct = temp.shape - - -# Templete matching -i, j = -1, -1 -v = 255 * H * W * C -for y in range(H-Ht): - for x in range(W-Wt): - _v = np.sum((img[y:y+Ht, x:x+Wt] - temp) ** 2) - if _v < v: - v = _v - i, j = x, y - -out = img.copy() -cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) -out = out.astype(np.uint8) +template = cv2.imread("imori_part.jpg").astype(np.float32) + +# Template matching +out = Template_matching(img, template) + # Save result cv2.imwrite("out.jpg", out) diff --git a/Question_51_60/answers/answer_55.py b/Question_51_60/answers/answer_55.py index 5b5443de..63435818 100644 --- a/Question_51_60/answers/answer_55.py +++ b/Question_51_60/answers/answer_55.py @@ -2,28 +2,46 @@ import numpy as np import matplotlib.pyplot as plt +# template matching +def Template_matching(img, template): + # get original image shape + H, W, C = img.shape + + # get template image shape + Ht, Wt, Ct = template.shape + + # Templete matching + # prepare x, y index + i, j = -1, -1 + # prepare evaluate value + v = 255 * H * W * C + + for y in range(H - Ht): + for x in range(W - Wt): + # get SAD value + _v = np.sum(np.abs(img[y : y + Ht, x : x + Wt] - template)) + + # if SAD is min + if _v < v: + v = _v + i, j = x, y + + out = img.copy() + # draw rectangle + cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) + out = out.astype(np.uint8) + + return out + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape # Read templete image -temp = cv2.imread("imori_part.jpg").astype(np.float32) -Ht, Wt, Ct = temp.shape - - -# Templete matching -i, j = -1, -1 -v = 255 * H * W * C -for y in range(H-Ht): - for x in range(W-Wt): - _v = np.sum(np.abs(img[y:y+Ht, x:x+Wt] - temp)) - if _v < v: - v = _v - i, j = x, y - -out = img.copy() -cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) -out = out.astype(np.uint8) +template = cv2.imread("imori_part.jpg").astype(np.float32) + +# Template matching +out = Template_matching(img, template) + # Save result cv2.imwrite("out.jpg", out) diff --git a/Question_51_60/answers/answer_56.py b/Question_51_60/answers/answer_56.py index dae7c407..fb3a0cbb 100644 --- a/Question_51_60/answers/answer_56.py +++ b/Question_51_60/answers/answer_56.py @@ -2,29 +2,48 @@ import numpy as np import matplotlib.pyplot as plt +# template matching +def Template_matching(img, template): + # get original image shape + H, W, C = img.shape + + # get template image shape + Ht, Wt, Ct = template.shape + + # Templete matching + # prepare x, y index + i, j = -1, -1 + # prepare evaluate value + v = -1 + + for y in range(H - Ht): + for x in range(W - Wt): + # get NCC value + # get numerator of NCC + _v = np.sum(img[y : y + Ht, x : x + Wt] * template) + # devided numerator + _v /= (np.sqrt(np.sum(img[y : y + Ht, x : x + Wt] ** 2)) * np.sqrt(np.sum(template ** 2))) + + # if NCC is max + if _v > v: + v = _v + i, j = x, y + + out = img.copy() + # draw rectangle + cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) + out = out.astype(np.uint8) + + return out + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape # Read templete image -temp = cv2.imread("imori_part.jpg").astype(np.float32) -Ht, Wt, Ct = temp.shape - - -# Templete matching -i, j = -1, -1 -v = -1 -for y in range(H-Ht): - for x in range(W-Wt): - _v = np.sum(img[y:y+Ht, x:x+Wt] * temp) - _v /= (np.sqrt(np.sum(img[y:y+Ht, x:x+Wt]**2)) * np.sqrt(np.sum(temp**2))) - if _v > v: - v = _v - i, j = x, y - -out = img.copy() -cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) -out = out.astype(np.uint8) +template = cv2.imread("imori_part.jpg").astype(np.float32) + +# Template matching +out = Template_matching(img, template) # Save result cv2.imwrite("out.jpg", out) diff --git a/Question_51_60/answers/answer_57.jpg b/Question_51_60/answers/answer_57.jpg index cd04e0770a6ab40c8f70933bf7b0d4c93ca7b181..59009f0e5ae84fcb252dd41d622332fe85e74592 100644 GIT binary patch delta 6018 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 v: + v = _v + i, j = x, y + + out = img.copy() + # draw rectangle + cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) + out = out.astype(np.uint8) + + return out + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape - -mi = np.mean(img) # Read templete image -temp = cv2.imread("imori_part.jpg").astype(np.float32) -Ht, Wt, Ct = temp.shape - -mt = np.mean(temp) - -# Templete matching -i, j = -1, -1 -v = -1 -for y in range(H-Ht): - for x in range(W-Wt): - _v = np.sum((img[y:y+Ht, x:x+Wt]-mi) * (temp-mt)) - _v /= (np.sqrt(np.sum((img[y:y+Ht, x:x+Wt]-mi)**2)) * np.sqrt(np.sum((temp-mt)**2))) - if _v > v: - v = _v - i, j = x, y - -out = img.copy() -cv2.rectangle(out, pt1=(i, j), pt2=(i+Wt, j+Ht), color=(0,0,255), thickness=1) -out = out.astype(np.uint8) - +template = cv2.imread("imori_part.jpg").astype(np.float32) + +# Template matching +out = Template_matching(img, template) + + # Save result cv2.imwrite("out.jpg", out) cv2.imshow("result", out) diff --git a/Question_51_60/answers/answer_58.py b/Question_51_60/answers/answer_58.py index 160c3995..3ca9890d 100644 --- a/Question_51_60/answers/answer_58.py +++ b/Question_51_60/answers/answer_58.py @@ -2,56 +2,79 @@ import numpy as np import matplotlib.pyplot as plt -# Read image -img = cv2.imread("seg.png").astype(np.float32) -H, W, C = img.shape - -label = np.zeros((H, W), dtype=np.int) -label[img[..., 0]>0] = 1 - -LUT = [0 for _ in range(H*W)] - -n = 1 - -for y in range(H): - for x in range(W): - if label[y, x] == 0: - continue - c3 = label[max(y-1,0), x] - c5 = label[y, max(x-1,0)] - if c3 < 2 and c5 < 2: - n += 1 - label[y, x] = n - else: - _vs = [c3, c5] - vs = [a for a in _vs if a > 1] - v = min(vs) - label[y, x] = v +# labeling 4 nearest neighbor +def labeling_4nn(img): + # get image shape + H, W, C = img.shape + + # prepare label tempolary image + label = np.zeros((H, W), dtype=np.int) + label[img[..., 0]>0] = 1 + + # look up table + LUT = [0 for _ in range(H*W)] + + n = 1 + + for y in range(H): + for x in range(W): + # skip black pixel + if label[y, x] == 0: + continue - minv = v - for _v in vs: - if LUT[_v] != 0: - minv = min(minv, LUT[_v]) - for _v in vs: - LUT[_v] = minv + # get above pixel + c3 = label[max(y-1,0), x] + + # get left pixel + c5 = label[y, max(x-1,0)] + + # if not labeled + if c3 < 2 and c5 < 2: + # labeling + n += 1 + label[y, x] = n + else: + # replace min label index + _vs = [c3, c5] + vs = [a for a in _vs if a > 1] + v = min(vs) + label[y, x] = v -count = 1 - -for l in range(2, n+1): - flag = True - for i in range(n+1): - if LUT[i] == l: - if flag: - count += 1 - flag = False - LUT[i] = count - -COLORS = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [255, 255, 0]] -out = np.zeros((H, W, C), dtype=np.uint8) - -for i, lut in enumerate(LUT[2:]): - out[label == (i+2)] = COLORS[lut-2] + minv = v + for _v in vs: + if LUT[_v] != 0: + minv = min(minv, LUT[_v]) + for _v in vs: + LUT[_v] = minv + + count = 1 + + # integrate index of look up table + for l in range(2, n+1): + flag = True + for i in range(n+1): + if LUT[i] == l: + if flag: + count += 1 + flag = False + LUT[i] = count + + # draw color + COLORS = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [255, 255, 0]] + out = np.zeros((H, W, C), dtype=np.uint8) + + for i, lut in enumerate(LUT[2:]): + out[label == (i+2)] = COLORS[lut-2] + + return out + +# Read image +img = cv2.imread("seg.png").astype(np.float32) + +# labeling 4 nearest neighbor +out = labeling_4nn(img) + # Save result cv2.imwrite("out.png", out) cv2.imshow("result", out) diff --git a/Question_51_60/answers/answer_59.py b/Question_51_60/answers/answer_59.py index a5431167..752e09b3 100644 --- a/Question_51_60/answers/answer_59.py +++ b/Question_51_60/answers/answer_59.py @@ -2,58 +2,80 @@ import numpy as np import matplotlib.pyplot as plt + +# labeling 8 nearest neighbor +def labeling_8nn(img): + # get image shape + H, W, C = img.shape + + # prepare labeling image + label = np.zeros((H, W), dtype=np.int) + label[img[..., 0]>0] = 1 + + # look up table + LUT = [0 for _ in range(H*W)] + + n = 1 + + for y in range(H): + for x in range(W): + if label[y, x] == 0: + continue + # get right top pixel + c2 = label[max(y-1,0), min(x+1, W-1)] + # get top pixel + c3 = label[max(y-1,0), x] + # get left top pixel + c4 = label[max(y-1,0), max(x-1,0)] + # get left pixel + c5 = label[y, max(x-1,0)] + + # if all pixel is non labeled + if c3 < 2 and c5 < 2 and c2 < 2 and c4 < 2: + n += 1 + label[y, x] = n + else: + # get labeled index + _vs = [c3, c5, c2, c4] + vs = [a for a in _vs if a > 1] + v = min(vs) + label[y, x] = v + + minv = v + for _v in vs: + if LUT[_v] != 0: + minv = min(minv, LUT[_v]) + for _v in vs: + LUT[_v] = minv + + count = 1 + + # integrate labeled index of look up table + for l in range(2, n+1): + flag = True + for i in range(n+1): + if LUT[i] == l: + if flag: + count += 1 + flag = False + LUT[i] = count + + # draw color + COLORS = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [255, 255, 0]] + out = np.zeros((H, W, C), dtype=np.uint8) + + for i, lut in enumerate(LUT[2:]): + out[label == (i+2)] = COLORS[lut-2] + + return out + + # Read image img = cv2.imread("seg.png").astype(np.float32) -H, W, C = img.shape - -label = np.zeros((H, W), dtype=np.int) -label[img[..., 0]>0] = 1 - -LUT = [0 for _ in range(H*W)] - -n = 1 - -for y in range(H): - for x in range(W): - if label[y, x] == 0: - continue - c2 = label[max(y-1,0), min(x+1, W-1)] - c3 = label[max(y-1,0), x] - c4 = label[max(y-1,0), max(x-1,0)] - c5 = label[y, max(x-1,0)] - if c3 < 2 and c5 < 2 and c2 < 2 and c4 < 2: - n += 1 - label[y, x] = n - else: - _vs = [c3, c5, c2, c4] - vs = [a for a in _vs if a > 1] - v = min(vs) - label[y, x] = v - - minv = v - for _v in vs: - if LUT[_v] != 0: - minv = min(minv, LUT[_v]) - for _v in vs: - LUT[_v] = minv - -count = 1 - -for l in range(2, n+1): - flag = True - for i in range(n+1): - if LUT[i] == l: - if flag: - count += 1 - flag = False - LUT[i] = count - -COLORS = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [255, 255, 0]] -out = np.zeros((H, W, C), dtype=np.uint8) - -for i, lut in enumerate(LUT[2:]): - out[label == (i+2)] = COLORS[lut-2] - + +# labeling 8 nearest neighbor +out = labeling_8nn(img) + # Save result cv2.imwrite("out.png", out) cv2.imshow("result", out) diff --git a/Question_51_60/answers/answer_60.py b/Question_51_60/answers/answer_60.py index 7003d590..bbac60d1 100644 --- a/Question_51_60/answers/answer_60.py +++ b/Question_51_60/answers/answer_60.py @@ -2,15 +2,21 @@ import numpy as np import matplotlib.pyplot as plt + +# alpha blend +def alpha_blend(img1, img2, alpha): + # blend + out = img * alpha + img2 * (1 - alpha) + out = out.astype(np.uint8) + return out + # Read image img = cv2.imread("imori.jpg").astype(np.float32) -H, W, C = img.shape +# Read blend target image img2 = cv2.imread("thorino.jpg").astype(np.float32) -a = 0.6 -out = img * a + img2 * (1 - a) -out = out.astype(np.uint8) +out = alpha_blend(img, img2, alpha=0.6) # Save result cv2.imwrite("out.jpg", out) diff --git a/README.md b/README.md index 7665825f..d87c3852 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ PythonとC++の好きな方でやってみてね♡(最近Javascriptも追加 ## Recent -- 2019.8.18 [Python] Q.50までコードの処理をメソッド化 +- 2019.8.28 [Python] Q.51~60のAnswerコードをメソッド化 +- 2019.8.18 [Python] Q.50までのAnswerコードをメソッド化 - 2019.8.12 [C++]Q.36-40の解答追加 - 2019.7.32 [C++]Q.32-35の解答追加 - 2019.7.23 [C++]Q.30-31の解答追加