🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

NumPy

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

OpenCV

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

PyCharm

エディター・開発ツール

Q&A

解決済

1回答

1352閲覧

初めてのOpenCV

oinari03

総合スコア59

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

NumPy

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

OpenCV

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

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

PyCharm

エディター・開発ツール

0グッド

0クリップ

投稿2019/11/08 07:09

編集2019/11/08 07:23

やりたいこと

以下の輪郭抽出して背景を透過した画像の
①RGB値(比率)?の取得
②画像の大きさpx値として表示
③輪郭抽出した中身の画像の重心を取得したい
イメージ説明

書いたコード

python

1import cv2 2import numpy as np 3 4# 画像を読み込む。 5img = cv2.imread(r"C:\Users\hirayama\Desktop\python_test\Python.png") 6 7# グレースケールに変換する。 8gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 9 10# 2値化する。 11thresh, binary = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV) 12 13# 輪郭を抽出する。 14contours, hierarchy = cv2.findContours( 15 binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE 16) 17 18# マスクを作成する 19mask = np.zeros_like(binary) 20 21# 輪郭内部(透明化しない画素)を255で塗りつぶす。 22for cnt in contours: 23 cv2.drawContours(mask, contours, -1, color=255, thickness=-1) 24 25# RGBAに変換する 26rgba = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA) 27 28# マスクをアルファチャンネルに設定する。 29rgba[..., 3] = mask 30 31 32# すべての輪郭を描画 33#cv2.drawContours(img, contours, -1, color=(0, 255, 0), thickness=2) 34 35# 保存する。 36cv2.imwrite(r"C:\Users\hirayama\Desktop\python_test\rgba_Python.png", rgba) 37 38# BGR値の取得 39BGR = rgba[100, 100] 40print(BGR) 41 42# 画像の大きさ(px) 43print(rgba.size) 44 45# 表示 46cv2.imshow("img", rgba) 47cv2.waitKey(0) 48 49

実行結果

BGR値の取得
BGR = rgba[100, 100]
print(BGR)

画像の大きさ(px)
print(rgba.size)

[255 255 255 0]
7060548

のような値で全部255っておかしいかですよね。たぶん。重心の求め方に関してはmoments関数を使うことしかわからなくて実装できません。

解決してほしいこと

コードをレビューしていただきたいです。また、実行結果からRGB値の値が正しいのか、他のやりかたがあるのか教えてほしいです。
最後に、全然分からないので、contoursした画像の重心を求めるコードを教えていただけるとうれしいです。
超初心者ですので、失礼がありましたら、申し訳ありません。

追記

重心のコードを書いてみましたが、はたして、輪郭内部の重心であっているのでしょうか?

python

1# 重心を求める 2cnt = contours[0] 3M = cv2.moments(cnt) 4print(M) 5cx = int(M['m10']/M['m00']) 6cy = int(M['m01']/M['m00']) 7print((cx, cy))

実行結果
{'m00': 3630.0, 'm10': 2613283.6666666665, 'm01': 3195271.1666666665, 'm20': 1883025588.0, 'm11': 2299330490.583333, 'm02': 2818133066.5, 'm30': 1358054429772.7002, 'm21': 1656066366000.6167, 'm12': 2027034542877.3167, 'm03': 2490427057352.85, 'mu20': 1689080.433394909, 'mu11': -986300.1662378311, 'mu02': 5527604.094666958, 'mu30': 8119675.634277344, 'mu21': -27959950.409425497, 'mu12': -39319440.03291702, 'mu03': 62396420.001464844, 'nu20': 0.1281849625780653, 'nu11': -0.07485069828547161, 'nu02': 0.41949199695428796, 'nu30': 0.01022756192602152, 'nu21': -0.03521841723007951, 'nu12': -0.049526856237396895, 'nu03': 0.07859467277646077}

(719, 880)

輪郭内部の画像の重心を取得できたのかわかりません
別の書き方を教えてほしいです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

全部255っておかしいかですよね。

おかしくないです。RGBA=(255, 255, 255, 0) ということは、白でアルファチャンネルが0の画素を意味します。
実際、画像の (100, 100) の位置の画素は白になってます。(アルファチャンネル0なので透過されてますが)

画像の重心を求めるコードを教えていただけるとうれしいです。

cv2.moments() に輪郭を渡して帰ってくるモーメントを使って、重心は以下のように計算できます。

python

1# 各輪郭の重心を計算する。 2for i, cnt in enumerate(contours): 3 M = cv2.moments(cnt) 4 cx = int(M["m10"] / M["m00"]) 5 cy = int(M["m01"] / M["m00"]) 6 print(f"contour {i}: ({cx}, {cy})")

領域(輪郭)の特徴 — OpenCV-Python Tutorials 1 documentation

輪郭抽出した画像の中身だけの画像の指定方法を教えていただけませんか?

python

1import cv2 2import numpy as np 3 4# 画像を読み込む。 5img = cv2.imread(r"sample.png") 6 7# グレースケールに変換する。 8gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 9 10# 2値化する。 11thresh, binary = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV) 12 13# 輪郭を抽出する。 14contours, hierarchy = cv2.findContours( 15 binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE 16) 17 18# マスクを作成する 19mask = np.zeros_like(binary) 20 21# 輪郭内部(透明化しない画素)を255で塗りつぶす。 22cv2.drawContours(mask, contours, -1, color=255, thickness=-1) 23 24# RGBAに変換する 25rgba = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA) 26 27# マスクをアルファチャンネルに設定する。 28rgba[..., 3] = mask 29 30### 追加したコード 31 32# すべての輪郭を構成する点 33all_points = np.concatenate(contours).reshape(-1, 2) 34 35# x, y の最小値、最大値を探す。 36xmin, ymin, xmax, ymax = ( 37 all_points[:, 0].min(), 38 all_points[:, 1].min(), 39 all_points[:, 0].max(), 40 all_points[:, 1].max(), 41) 42# その範囲でクロップする。 43cropped = rgba[ymin:ymax + 1, xmin:xmax + 1] 44print(cropped.shape) # (419, 852, 4) 45 46# 保存する。 47cv2.imwrite(r"cropped.png", cropped) 48 49# BGR値の取得 50print(cropped[200, 200]) # [167 116 55 255] 51 52# 画像の大きさ(px) 53h, w = cropped.shape[:2] 54print(w, h) # 624 852

投稿2019/11/08 07:23

編集2019/11/08 07:53
tiitoi

総合スコア21956

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

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

oinari03

2019/11/08 07:41

重心の回答ありがとうございます!! 本当に助かります!!! 私のミスというか知識不足で、画像の中身のRGB値を取得するつもりだったのですがすべて(100,100)で指定していました。 輪郭抽出した画像の中身だけの画像の指定方法を教えていただけませんか?
tiitoi

2019/11/08 07:54

contours の点の中で一番左上の点と一番右下の点を探して、その範囲で画像をクロップすればよいです。 コードを追記しました。
oinari03

2019/11/08 15:14

ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問