electronicsdiy / electronics_diy721

electronics_diy721's repository
0 stars 0 forks source link

OpenCV2 Contour Area Percentage Calculation #8

Open electronicsdiy opened 3 years ago

electronicsdiy commented 3 years ago

Reference website

Output

All_detected_parts_black_and_white_nozomi_1 jpg

All_detected_parts_nozomi_1 jpg

result_black_and_white_nozomi_1 jpg275

result_nozomi_1 jpg275

result_black_and_white_nozomi_1 jpg173

result_nozomi_1 jpg173

result_black_and_white_nozomi_1 jpg344

result_nozomi_1 jpg344

Code

import cv2

from typing import Tuple, Optional
import os
import cv2
import numpy as np
import cv2
import argparse

# 動画ファイル名をコマンドライン引数から受け取る
parser = argparse.ArgumentParser(description='')    #
parser.add_argument('--file_name')
args = parser.parse_args()

img_file = args.file_name

im = cv2.imread(img_file)
im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
retval, im_bw = cv2.threshold(im_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 輪郭の検出
contours, hierarchy = cv2.findContours(im_bw, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# 輪郭を1つずつ書き込んで出力
# 何も出力されないか、かろうじて視認できる点しか書き込まれないものは、画像に出力しない
# 面積が100ピクセル以上のものみ、青色で輪郭を1件ずつ個別のファイルに出力。
# 検出されたすべての面積は、その輪郭のいかんによらず、detected_all_the_contours_resultにすべてまとめて出力する。
for i in range(len(contours)):
    im_con = im.copy()
    im_con = cv2.drawContours(im_con, contours, i, (255, 191, 0), 10) # dep skyblue RGB(0, 191, 255)
    #検出したパーツが、画面全体に占める面積比を求める
    #この画像ファイルを真っ黒にしたnumpy.array行列オブジェクトを作成
    im_con2 = im.copy()
    img_gray = cv2.cvtColor(im_con2, cv2.COLOR_BGR2GRAY)
    this_image_file_size_all_element_zero_image = np.zeros_like(img_gray)
    #https://code-graffiti.com/opencv-contour-detection-in-python/
    #第5引数で輪郭線の太さを指定。-1を指定すると塗りつぶしになる。色はスカラー0で黒((0,0,0)と同義)、255で白((255,255,255)と同義)
    cv2.drawContours(this_image_file_size_all_element_zero_image, contours, i, color=255, thickness=-1)
    # 白黒割合の確認
    image_size = this_image_file_size_all_element_zero_image.size #画面全体の面積
    white_pixels = cv2.countNonZero(this_image_file_size_all_element_zero_image)
    #すぐ上のdarwCounterでパーツ領域だけ白で塗りつぶされている。NonZeroの値が、その白い画素部分
    black_pixels = int(this_image_file_size_all_element_zero_image.size)-int(white_pixels)
    #cv2.countZeroメソッドがないので、全体から白領域を引いて黒領域の面積を得る
    area_percentage = (white_pixels/image_size)*100
    # 小数点第2位まで出力
    area_percentage_str = format(area_percentage, '.2f')

    message0 =  "ID : {0}  ,  Area {1}%".format(i, area_percentage_str)
    message1 =  "Area {0} of All Area {1}".format(cv2.contourArea(contours[i]), image_size)

    print(message0)
    print(message1+"\n")

    if cv2.contourArea(contours[i]) >= 100:
        cv2.putText(im_con, str(message0),  (0, 50), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 0, 255), 1, cv2.LINE_AA)
        cv2.putText(im_con, str(message1),  (0, 80), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 0, 255), 1, cv2.LINE_AA)
        cv2.imwrite('result_' + img_file + str(i) + '.png', im_con)

        cv2.putText(this_image_file_size_all_element_zero_image, str(message0),  (0, 50), cv2.FONT_HERSHEY_TRIPLEX, 1, 255, 1, cv2.LINE_AA)
        cv2.putText(this_image_file_size_all_element_zero_image, str(message1),  (0, 80), cv2.FONT_HERSHEY_TRIPLEX, 1, 255, 1, cv2.LINE_AA)
        cv2.imwrite('result_black_and_white_' + img_file + str(i) + '.png', this_image_file_size_all_element_zero_image)
    else:
        pass

# 検出されたすべての輪郭を画像に書き込んでファイル出力
im_new = cv2.imread(img_file) #im_conには、ループ処理の最終回でcv2.putTextで書き込んだ内容が残っている。新しいイメージオブジェクトを取得。
all_counours_engraved_img = cv2.drawContours(im_new, contours, -1, (0, 250, 154), 3)
#cv2.imwrite('detected_all_the_contours_result' + img_file + '.png', all_counours_engraved_img)

#この画像ファイルを真っ黒にしたnumpy.array行列オブジェクトを作成
im_con3 = im_new.copy()
img_gray2 = cv2.cvtColor(im_con3, cv2.COLOR_BGR2GRAY)
all_element_zero_image = np.zeros_like(img_gray2)
#第5引数で輪郭線の太さを指定。-1を指定すると塗りつぶしになる。色はスカラー0で黒((0,0,0)と同義)、255で白((255,255,255)と同義)
cv2.drawContours(all_element_zero_image, contours, -1, color=255, thickness=-1)
# 白黒割合の確認
image_size = this_image_file_size_all_element_zero_image.size #画面全体の面積
white_pixels2 = cv2.countNonZero(all_element_zero_image)
#すぐ上のdarwCounterでパーツ領域だけ白で塗りつぶされている。NonZeroの値が、その白い画素部分
black_pixels = int(all_element_zero_image.size)-int(white_pixels2)
#cv2.countZeroメソッドがないので、全体から白領域を引いて黒領域の面積を得る
all_area_percentage = (white_pixels2/image_size)*100
# 小数点第2位まで出力
all_area_percentage_str = format(all_area_percentage, '.2f')

message2 =  "ID : NA  ,  Area {0}%".format(all_area_percentage_str)
message3 =  "Area {0} of All Area {1}".format(white_pixels2, image_size)

print(message2)
print(message3+"\n")

# 原画像(カラー色)に検出されたすべてのパーツの輪郭と面積比率を記入した画像
cv2.putText(im_con3, str(message2),  (0, 50), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.putText(im_con3, str(message3),  (0, 80), cv2.FONT_HERSHEY_TRIPLEX, 1, (0, 0, 255), 1, cv2.LINE_AA)

cv2.imwrite('All_detected_parts_' + img_file + '.png', im_con3)
# 上記を白黒にした画像
cv2.putText(all_element_zero_image, str(message2),  (0, 50), cv2.FONT_HERSHEY_TRIPLEX, 1, 255, 1, cv2.LINE_AA)
cv2.putText(all_element_zero_image, str(message3),  (0, 80), cv2.FONT_HERSHEY_TRIPLEX, 1, 255, 1, cv2.LINE_AA)
cv2.imwrite('All_detected_parts_black_and_white_' + img_file  + '.png', all_element_zero_image)