2
5

More than 1 year has passed since last update.

OpenCV(Python)で手のひらの面積を算出する

Last updated at Posted at 2022-01-30

OpenCV

pip install opencv-python

手順の概要

1.方眼の上で手のひらの画像を撮る
2.方眼の部分だけを残しトリミング
3.OpenCVで読み込んでグレースケール・二値化(python)
4.二値化した画像で手のひらの輪郭を探索(python)
5.「手のひらのピクセル数」と「全体のピクセル数」の比により面積を算出(python)

1.2.画像取得とトリミング

取得した画像
S__13139991.jpg
トリミング後
S__13139993.jpg

3.OpenCVでグレースケール・二値化

img = cv2.imread("hand.jpg")  # 画像データの取得

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 白黒(グレースケール)化
threshold = 160  # 二値化の閾値
ret, thresh = cv2.threshold(gray, threshold, 255, cv2.THRESH_BINARY) #  閾値での二値化

二値化後の画像
hand_gray.jpg

4.5.手のひらの輪郭を探索・面積を算出

contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 輪郭を取得
contours = list(filter(lambda x: cv2.contourArea(x) > 20000, contours))  # 小さい輪郭を除く

height, width = img.shape[0], img.shape[1]  # 縦・横のピクセル数を取得
rectangle_area = height * width  # 総ピクセル数
rate = cv2.contourArea(contours[0]) / rectangle_area  # 手のピクセル数が全体のピクセル数に占める割合
bg_area = 19*28  # 青色の背景の面積[cm^2]
hand_S = round(bg_area*rate, 3)  # 手の面積[cm^2]
手のひらの面積S=\frac{手のひらのピクセル数}{画像全体のピクセル数}・方眼の面積[\rm{cm^2}]

S__13139994.jpg

結果

私(男性)の手のひらの面積は$150.4\rm{cm^2}$と算出できた。
[1]によると、手のひらの面積の平均値は、男性$140\rm{cm^2}$、女性$120\rm{cm^2}$とのことだったので、妥当な結果だと言える。

コード全体

import cv2

#############################
# 画像取り込み
img = cv2.imread("hand7.jpg")  # 画像データの取得
height, width = img.shape[0], img.shape[1]  # 縦・横のピクセル数を取得
scale = 1  # 表示倍率
height2, width2 = img.shape[0]*scale, img.shape[1]*scale  # 表示用の縦・横のピクセル数
rectangle_area = height2 * width2  # 総ピクセル数
img = cv2.resize(img, (int(width2), int(height2)))  # 指定した倍率にリサイズ

#############################
#グレースケール・二値化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 白黒(グレースケール)化
threshold = 160  # 二値化の閾値
ret, thresh = cv2.threshold(gray, threshold, 255, cv2.THRESH_BINARY) #  閾値での二値化
# ret, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)  # 自動二値化

#############################
#輪郭の探索・面積の算出
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 輪郭を取得
contours = list(filter(lambda x: cv2.contourArea(x) > 20000, contours))  # 小さい輪郭を除く
rate = cv2.contourArea(contours[0]) / rectangle_area  # 手のピクセル数が全体のピクセル数に占める割合
bg_area = 19*28  # 青色の背景の面積[cm^2]
hand_S = round(bg_area*rate, 3)  # 手の面積[cm^2]
print(str(hand_S)+"[cm^2]")
cv2.putText(img, str(hand_S)+"cm^2", org=(int(height2/2), int(width2/2)),  # 画像内に面積表示
            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
            fontScale=5.0,
            color=(0, 0, 0),
            thickness=5,
            lineType=cv2.LINE_4)

cv2.drawContours(img, contours, -1, color=(0, 0, 255), thickness=5)  # 輪郭の描画

#############################
# 画像保存
cv2.imwrite("hand_result.jpg", img)
cv2.imwrite("hand_gray.jpg", thresh)

#############################
# 画像表示
cv2.imshow("img", img)
cv2.imshow("img2", thresh)
cv2.waitKey (0)
cv2.destroyAllwindows()

#############################

参考文献

[1] 服部恒明; 大槻文夫. 成人の手部平面積の非対称性について. 体育学研究, 1974, 19.3: 133-136.

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5