質問するログイン新規登録
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4472閲覧

画像の閉鎖領域内における白と黒の割合を求めたい

itsuko

総合スコア17

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/04/07 04:01

編集2021/04/07 05:20

0

0

前提・実現したいこと

2値化画像における,閉領域内の白と黒の比率を求めたいです.

該当のソースコード

Python

1 2import cv2 3import numpy as np 4# ----------------------------   2値化  --------------------------- 5 6img = cv2.imread('C:.../input.png') # color scale 7gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # gray scale 8ret, binary = cv2.threshold(gray,0, 255, cv2.THRESH_OTSU) 9cv2.imwrite('C:.../binary.png', binary) 10 11# 輪郭抽出 12contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 13 14 15 16# ----------------------------   2値化後の面積を算出  --------------------------- 17out = np.zeros_like(gray) 18max_cnt = max(contours, key=lambda x: cv2.contourArea(x)) 19max_area = cv2.contourArea(max_cnt) 20white_area = cv2.countNonZero(binary) 21image_size = binary.size 22ratio = (1-white_area/max_area)*100 23print("白の面積:",white_area," 輪郭内の面積:",max_area,"求める割合:",ratio)

試したこと

cv2.contourAreaを用いると,領域内の面積が出せると思いますが,グリーンの定理によって厳密なピクセル数ではないという記載があったので,できれば面積の比ではなく,ピクセルの比で求めたいと考えています.
上のソースでは輪郭内の面積をcontourAreaで,白の面積をcountNonZeroから求めているため,ratioの値が負になってしまいました.
なお,領域外にも白色の面積はありますが,ごく微小のため,ソースコードでは領域外の白色面積は無いものとして書いています.

(補足説明/ツールのバージョンなど)

画像は次のようなものです.繰り返しになりますが,白長方形の面積(領域内の面積)と,その内部にある黒の面積の比率を求めたいです.
input.png
イメージ説明

binary.png
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Python

1# 黒い画像に一番大きい輪郭だけ塗りつぶして描画 → 塗りつぶし範囲のみを面積抽出 2gray = cv2.cvtColor("input.png", cv2.COLOR_BGR2GRAY) # gray scale 3out = np.zeros_like(gray) 4max_cnt = max(contours, key=lambda x: cv2.contourArea(x)) 5max_area = cv2.contourArea(max_cnt) 6cv2.drawContours(out, [max_cnt], -1, color=100, thickness=-1) # 一番大きい領域の塗りつぶし 7whole_area = len(np.where(out == 100)[0])

にて領域内の面積を求めることができました.

投稿2021/04/07 13:39

itsuko

総合スコア17

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

要は,「画素の個数を数えたい」という話ですよね.
contourAreaだと問題がある,ということであるならば,単に画像を自前で走査して数えてやればよいだけの話ではないのでしょうか?

[追記]
自前で数えるかわりに,connectedComponentsWithStats あたりが利用できるかもしれません.


それはそれとして,現状のコードがやりたいことに合っていない(=求めたい比率を計算する形になっていない)ように見えます.

> max_area = cv2.contourArea(max_cnt)

は,2値画像の3つの白い領域のうちの1つの領域だけを相手にして面積を求めており,
他方,

> white_area = cv2.countNonZero(binary)

では,2値画像の白い画素の総数(:3つの領域全ての面積の総和)を求めています.
故に,white_area/max_areaは1よりも大きくなるでしょう.

white_area = cv2.countNonZero(binary)

は,2値画像の白い画素の総数(:3つの白い領域全ての面積の総和)を求めており,
無関係な2つの領域を含む形になっています.

投稿2021/04/07 04:54

編集2021/04/07 05:21
fana

総合スコア12299

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

itsuko

2021/04/07 05:27 編集

回答ありがとうございます. 肝心な点を書き漏らしておりました.ご指摘の通り,countNonZero(binary)では3つの領域全てを求めてしまっておりますが,実際の写真ではかなり微小部のため(写真では大きいですが...),無視して考えておりました.すみません.質問内容を編集し,変更しました. 手前の都合で恐縮ですが,なるべく金銭的な負担のない道具のみで求めたく思っております. プログラミングに拘る必要はないのですが,Pythonでは何かよい関数・ライブラリ等はございませんでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問