質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Python

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

Q&A

解決済

1回答

4175閲覧

Pythonで白黒画像とカラー画像の判別

redp

総合スコア49

Python 3.x

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

Python

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

0グッド

1クリップ

投稿2018/12/23 04:32

編集2018/12/23 08:31

実現したいこと

現在、18万枚の画像から白黒画像とカラー画像の判別をしているのですが精度を上げるためにどのような工夫をすればよいでしょうか?
画像はすべてイラストになります。
現在は以下のコードで行っています。コードは__StackOverflow__で拾ったものを改変しております。

コード

Python

1import cv2 2import os 3import shutil 4import numpy as np 5 6 7def judge(root): 8 for path in os.listdir(root): 9 # load image 10 img_path = os.path.join(root, path) 11 img = cv2.imread(img_path) 12 b, g, r = cv2.split(img) 13 14 r_g = np.count_nonzero(abs(r - g)) 15 r_b = np.count_nonzero(abs(r - b)) 16 g_b = np.count_nonzero(abs(g - b)) 17 diff_sum = float(r_g + r_b + g_b) 18 19 ratio = diff_sum / img.size 20 # color 21 if ratio > 0.005: 22 continue 23 # grey 24 else: 25 os.remove(img_path) 26 27 28if __name__ == '__main__': 29 judge('path/to/image_directory')

誤判定された画像

著作物のネットリテラシーが欠落していたので、引用元が確定したものだけ残しました。
イメージ説明
拝借元 > https://m-hakus.tumblr.com/(はくす様)

環境

Windows 10
Python 3.6

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

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

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

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

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

tiitoi

2018/12/23 06:06

なにが問題なのかわからないのですが、記載のコードでは判別できないので、どうすればいいか?という質問ですか?
can110

2018/12/23 06:48

誤判定する具体的な画像をアップいただくと回答得られやすくなります。
sakura_hana

2018/12/23 07:52

質問と直接関係無いですが、アップしている画像は自作品ですか? もしそうでないなら著作権違反となりますので、引用元と作成者を明記してください。
tiitoi

2018/12/23 09:01

パラメータである 0.005 を調整はしましたか?
redp

2018/12/23 09:19

パラメータを何回か変えて行いましたが精度という面では変わりませんでした。低評価もついてしまいましたし、自分でMLのハイパーパラメータのチューニング行う感覚で調整していこうと思います。
guest

回答1

0

ベストアンサー

画像処理は門外漢ですが、python detect color imageでググると以下がヒットしました。
Detect if image is color, grayscale or black and white with Python/PIL

上記を丸パクリし元に判定関数を作成してみました。
見た目では分からない程度でも色味に揺らぎがあるとカラーと判定されます。
よって実際の運用では、いきなりファイル削除せずに画像をフォルダに振り分けしてMaybe Colorな画像は
MAYBE_COLOR値をあげながら徐々に絞り込むような処理が必要かと思います。

※モデル:レナ姐さん

Python

1import cv2 2import numpy as np 3import os 4 5# モノクロ画像に変換 6def to_gray(path): 7 img = cv2.imread(path) 8 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 9 cv2.imwrite(os.path.splitext(path)[0] + '_gray.jpg', gray) 10 11# 彩度を変更 12def conv_saturation(path,sat): 13 img = cv2.imread(path) 14 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 15 h, s, v = cv2.split(hsv) 16 s[:,:] = sat 17 hsv = cv2.merge((h,s,v)); 18 img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) 19 cv2.imwrite('{}_sat{:03d}.jpg'.format(os.path.splitext(path)[0],sat), img) 20 21# 提示ソースの判定用の値 22def get_ratio(path): 23 img = cv2.imread(path) 24 25 b, g, r = cv2.split(img) 26 27 r_g = np.count_nonzero(abs(r - g)) 28 r_b = np.count_nonzero(abs(r - b)) 29 g_b = np.count_nonzero(abs(g - b)) 30 diff_sum = float(r_g + r_b + g_b) 31 32 return diff_sum / img.size # > 0.005 33 34# カラー画像か判定 35# Detect if image is color, grayscale or black and white with Python/PIL 36# https://stackoverflow.com/questions/20068945/detect-if-image-is-color-grayscale-or-black-and-white-with-python-pil 37def detect_color_image(file, MAYBE_COLOR = 100): 38 39 from PIL import Image, ImageStat 40 from functools import reduce 41 42 MONOCHROMATIC_MAX_VARIANCE = 0.005 43 COLOR = 1000 44 45 v = ImageStat.Stat(Image.open(file)).var # =分散 46 is_monochromatic = reduce(lambda x, y: x and y < MONOCHROMATIC_MAX_VARIANCE, v, True) 47 if is_monochromatic: 48 return "Monochromatic image" 49 else: 50 mes = '?' 51 if len(v)==3: # color 52 maxmin = abs(max(v) - min(v)) 53 if maxmin > COLOR: 54 mes = "Color" 55 elif maxmin > MAYBE_COLOR: 56 mes = "Maybe color" 57 else: 58 mes = "grayscale" 59 60 return '{}({})'.format(mes, maxmin) 61 62 elif len(v)==1: 63 return "Black and white" 64 else: 65 return "Don't know..." 66 67# テスト画像生成 68to_gray('lena.jpg') 69conv_saturation('lena.jpg',1) 70conv_saturation('lena.jpg',10) 71conv_saturation('lena.jpg',100) 72 73# 各画像を判定 74for path in ['lena.jpg','lena_gray.jpg','lena_sat001.jpg','lena_sat010.jpg','lena_sat100.jpg']: 75 print(path) 76 print(get_ratio(path)) # 提示ソースの判定値 77 print(detect_color_image(path)) 78 print() 79 80# 閾値を徐々にあげる 81path = 'lena_sat010.jpg' 82print(path) 83for maybe_color in [100,200,300]: 84 print(detect_color_image(path,maybe_color),maybe_color)

投稿2018/12/23 09:39

編集2018/12/23 09:44
can110

総合スコア38266

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

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

redp

2018/12/23 09:57

コメント付きで分かりやすい解答ありがとうございます。非常に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問