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

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

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

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

Q&A

3回答

930閲覧

Python:画像を「大きく・二色に・なめらかに」したい

kake_0819

総合スコア4

Python 3.x

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

0グッド

0クリップ

投稿2023/06/05 16:19

編集2023/06/07 20:50

実現したいこと

イメージ説明イメージ説明
・正方形の画像を1000×1000にリサイズする
・画像から最も頻度の高い2色を抽出する
・その2色で画像を置き換える
・出力された画像に違和感がないように、ふちを滑らかにするなどの処理を追加したい

!!!!!発生している問題!!!!!

・置き換え前のふち部分が、置き換え後におかしくなっている
・ふち部分がなめらかでない

ソースコードを求めているというよりは、アイデアを募集しています。

該当のソースコード

import cv2 import numpy as np def extract_top_colors(image, num_colors): #上位2色を抽出する関数 # 画像をリサイズ desired_size = (1000, 1000) resized_image = cv2.resize(image, desired_size) # 画像を1次元の配列に変換 pixels = resized_image.reshape(-1, 3) # 色の頻度を計算 unique_colors, color_counts = np.unique(pixels, axis=0, return_counts=True) # 頻度の高い色を抽出 top_colors_indices = np.argsort(color_counts)[::-1][:num_colors] top_colors = np.array(unique_colors[top_colors_indices]) return top_colors def replace_colors(image, top_colors): #色の置き換えを行う関数 # 画像の高さと幅を取得 height, width = image.shape[:2] # 画像を走査して近い値と入れ替える for y in range(height): for x in range(width): pixel = image[y, x] # 走査中のピクセル値 # ピクセル値とtop_colorsの各色との距離を計算 distances = np.linalg.norm(top_colors - pixel, axis=1) # 最も近い色のインデックスを取得 closest_index = np.argmin(distances) # 最も近い色でピクセル値を置き換える image[y, x] = top_colors[closest_index] return image def main(): # 画像の読み込み image = cv2.imread('Test.png') # 上位2つの色を抽出 num_colors = 2 top_colors = extract_top_colors(image, num_colors) # 色の置き換え processed_image = replace_colors(image, top_colors) # 処理後の画像の保存 cv2.imwrite('processed_image.png', processed_image) if __name__ == '__main__': main()

上:置き換え前 下:置き換え後

イメージ説明イメージ説明

変換前の画像の条件

①正方形であり、1000×1000ピクセル未満のもの
②添付画像のような、若干画質が荒いもの(ふちなど)
③(拡大するとふち部分が2色ではないですが)パっと見て2色である画像

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

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

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

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

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

y_waiwai

2023/06/05 23:44

まずは、なめらか、ってところをコード実装可能なようにきちんと定義することから始めよう。 なめらか、というのはどういうことなんでしょうか
fana

2023/06/06 01:16 編集

(自分はそのコード読めないので実装に関する具体的指摘はできませんが) 結果例だけを見ると,色の置き換え処理の実装が バグっている/目的に関して適切でない という話に思える. だって,結果が明らかに不自然. 世間一般で言うところの「減色処理」ではそんな結果にならない気がするので,「減色処理」の方法論等について調べてみてはどうでしょう?
jbpb0

2023/06/06 23:43

> ふち部分がギザギザしてます。これをなめらかにしたい ぼかしてから2値化したら、いかがでしょうか 参考 https://teratail.com/questions/204418 の質問の「図1」の、「左上」と「右上」と「右下」
guest

回答3

0

要素技術は2つあります。

画像処理はなるべくOpenCVの関数を使った方がラクです。

ぼかす
cv2.GaussianBlur

2値化する
cv2.threshold 閾値による
cv2.Laplacianエッジ検出
cv2.Cannyエッジ検出
cv2.kmeans減色処理
いずれの方法でも恐らくやりたいことができます。

あとは、手前みそですが私の回答例のURLを挙げます。


滑らかにする強硬策があるとすれば、以下のステップくらいしか思いつきません。

  1. ぼかした後に
  2. cv2.resize で既定の(例えば)x4四方に拡大(オプションで「cv2.INTER_LANCZOS4」を指定。なるべく滑らかに拡大)
  3. 減色処理なり二値化なりして、
  4. cv2.resize で既定のサイズに縮小(オプションで「cv2.INTER_NEAREST」を指定。2値化したまま縮小)

投稿2023/06/07 11:40

編集2023/06/07 11:50
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

メディアンフィルタを用いて解決しました。
残りの課題として、処理後画像のふち部分がギザギザしてます。これをなめらかにしたいです。
ここでいうなめらかというのは、2値化されたものを維持したまま見栄えをよくしたいということです。(ノイズは除去されてます)
なめらかさで言えば、処理前の方がパッと見て上ですが、2値を維持したまま行いたいです。

上:元画像 下:処理後画像
イメージ説明
イメージ説明

import cv2 import numpy as np def extract_top_colors(image, num_colors): #上位2色を抽出する関数 # 画像をリサイズ desired_size = (1000, 1000) resized_image = cv2.resize(image, desired_size) # 画像を1次元の配列に変換 pixels = resized_image.reshape(-1, 3) # 色の頻度を計算 unique_colors, color_counts = np.unique(pixels, axis=0, return_counts=True) # 頻度の高い色を抽出 top_colors_indices = np.argsort(color_counts)[::-1][:num_colors] top_colors = np.array(unique_colors[top_colors_indices]) return top_colors def replace_colors(image, top_colors): #色の置き換えを行う関数 # 画像の高さと幅を取得 height, width = image.shape[:2] # メディアンフィルタで色を置き換える for y in range(1, height - 1): for x in range(1, width - 1): neighbors = [ image[y-1, x-1], image[y-1, x], image[y-1, x+1], image[y, x-1], image[y, x], image[y, x+1], image[y+1, x-1], image[y+1, x], image[y+1, x+1] ] neighbors_median = np.median(neighbors, axis=0) distances = np.linalg.norm(top_colors - neighbors_median, axis=1) closest_index = np.argmin(distances) image[y, x] = top_colors[closest_index] return image def main(): # 画像の読み込み image = cv2.imread('Test2.png') #画像のリサイズ desired_size = (1000, 1000) resized_image = cv2.resize(image, desired_size) # 上位2つの色を抽出 num_colors = 2 top_colors = extract_top_colors(resized_image, num_colors) # 色の置き換え processed_image = replace_colors(resized_image, top_colors) # 処理後の画像の保存 cv2.imwrite('processed_image.png', processed_image) if __name__ == '__main__': main()

投稿2023/06/06 13:55

kake_0819

総合スコア4

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

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

0

「なめらか」というのがノイズの除去であると仮定して、

  • 画像を二値化して、最初に取得したヒストグラムの上位2色に置き換える
  • メディアンフィルタの処理を真似してみる(OpenCVの関数を使うこともできます)
  • k-means法による減色処理を実施してみる

等はいかがでしょうか。
ソースは求めていないということなので、詳しい処理はググってみてください。
どれかの手法だけではなく、いくつか組み合わせるのもアリかと思います。
また、OpenCVのフィルタ関数にはメディアン以外にも色々あり、どれも処理自体はそこまで複雑ではないはずなので、ぜひ色々調べてしっくる来るものを探してみてください。

投稿2023/06/06 04:04

AkiFuku

総合スコア129

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問