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

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

新規登録して質問してみよう
ただいま回答率
85.47%
OpenCV

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

Python 3.x

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

Q&A

解決済

1回答

1115閲覧

OpenCVを利用して画像をモノクロ&容量削減したいと思ったのですが…

tiqua_nibio

総合スコア62

OpenCV

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

Python 3.x

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

0グッド

1クリップ

投稿2022/09/21 08:09

前提

opencvを使っております。
画像をモノクロ化して、jpegとして保存を行っています。

実現したいこと

・画像のサイズ(xxxピクセル、yyyピクセル)は維持
・圧縮率はできるだけ上げない(拡大したときの画質を維持)
・グレースケールにして、ファイル容量を半分など、できるだけ落とす

発生している問題・エラーメッセージ

opencvで試しては見たのですが、ファイルの容量が下がりません。
おそらく、rgbの数値を入れる配列情報が残ったままになっているのでしょうか。

Photoshopでも同様のことをやってみましたが、グレースケールにして保存すると、ファイルサイズが小さくなっていることが確認できます。
Photoshopでやるような感じで、ファイルサイズを小さくできる方法をご存じであれば、教えていただけないでしょうか?

# ライブラリのインポート import cv2 # 画像の読み込み img = cv2.imread('data/src/lena.jpg') # 読み込んだ画像をグレースケール化 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 画像の保存 cv2.imwrite('/etc/tmp/after_Lena.jpg', img_gray)

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

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

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

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

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

jbpb0

2022/09/21 22:38 編集

> rgbの数値を入れる配列情報が残ったままになっているのでしょうか。 そうはなってないはずです コードの最後に print(img.shape) print(img_gray.shape) を追加して実行したら分かりますが、「img_gray」は次元が2次元に減ってます(カラー情報が無くなってます) 「cv2.imwrite()」では、データ(numpy配列)のshapeが「(縦, 横)」の場合はグレースケールで、「(縦, 横, 3)」の場合はカラーで保存されますので、「img_gray」を保存した「after_Lena.jpg」は、グレースケール画像のファイルのはずです コードの最後に cv2.imwrite('/etc/tmp/before_Lena.jpg', img) を追加して実行して、カラーのままのデータも保存して、「after_Lena.jpg」と「before_Lena.jpg」のサイズを比べてみてください カラーの「before_Lena.jpg」の方がファイルのサイズが大きくないですか? また、カラーで保存し直しただけの「before_Lena.jpg」は、オリジナルの「lena.jpg」よりもファイルのサイズが大きくないですか?
jbpb0

2022/09/21 23:01 編集

上記のようにして、もし「before_Lena.jpg」の方が「lena.jpg」よりもファイルのサイズが大きいなら、 > 圧縮率はできるだけ上げない が、「圧縮率を下げる」(あまり圧縮しない)になってるのでしょう その場合は、「cv2.imwrite()」で品質を指定して、「before_Lena.jpg」のサイズが「lena.jpg」と同じくらいになれば、圧縮率が「lena.jpg」とだいたい同じになると思いますので、それと同じ品質を指定して保存した「after_Lena.jpg」のサイズは、「lena.jpg」よりも小さくなるでしょう 参考 https://note.nkmk.me/python-opencv-imread-imwrite/ の「cv2.imwrite()で画像ファイルに保存」
tiqua_nibio

2022/09/22 03:08

yohhoyさん ありがとうございます。PYTHON上でコマンドとして実行する分としてはいいですね。 windowsで、mobaxtermの場合、pipなどの問題が絡み、少し扱いにくいように感じました。
tiqua_nibio

2022/09/22 03:12

jbpb0さん >を追加して実行したら分かりますが、「img_gray」は次元が2次元に減ってます(カラー情報が無くなってます) なるほど、確かにファイル容量はすこーしだけ、減少しているのは知っていたのですが、配列も変化はしていたのですね。していないと勘違いしておりました。 >また、カラーで保存し直しただけの「before_Lena.jpg」は、オリジナルの「lena.jpg」よりもファイルのサイズが大きくないですか? これも、デフォルトで圧縮率が30%ぐらいと体感的には感じております。 ですので、圧縮率を50や、95などにすると、やはりもとのファイルよりも容量が大きくなってしまうようですね。 圧縮率について、大小と容量の大小を勘違いしており、すいません。たしかにjbpb0さんの言う通りですね。
jbpb0

2022/09/22 04:20

先に書いたことと重複しますが、解像度(縦横の画素数)を変えずにカラーのままで保存した場合に、元の画像ファイルとサイズがだいたい同じになる「品質」に設定しないと、 > 圧縮率はできるだけ上げない(拡大したときの画質を維持) にはなりません そのように「品質」を設定した上で、グレースケールで保存したら、ファイルのサイズは元画像よりも小さくなるでしょう どんなツールを使おうとも、上記は共通だと思います
ikadzuchi

2022/09/24 18:42

> ファイル容量はすこーしだけ、減少している ということであれば、それが限度なのでしょう。 カラーをグレイスケールにしたところで劇的にファイル容量が少なくなるわけではありません。画像の内容や画質によりますが、せいぜい1割か2割減といったところです。 また、「グレイスケールJPEGで保存した画像」と比べて「カラーJPEGで保存した、内容はグレースケールの画像」は容量はほとんど増えません。試した範囲では2%~4%差でした。 OpenCVでグレイスケールJPEGが利用できないのかは分かりませんが、仮にカラーJPEGで保存されていたとしてもさほど状況に違いはありません。
tiqua_nibio

2022/09/29 05:34

> yohhoyさん ImageMagickツールを試しましたが、やはり小さくならないようです。 > ikadzuchiさん 確かに体感的に1-2割が限度と感じています。
jbpb0

2022/09/29 06:37 編集

opencvでのjpeg保存の「品質」(大きいほど画質がいい=圧縮しない)は、範囲が0〜100で、指定しないと95だそうです 95は上限100に近いので、デフォルト設定では、圧縮はかなり控えめですよね https://tat-pytone.hatenablog.com/entry/2021/04/25/114334 上記Webページの、「品質」を変えて保存した画像ファイルのサイズ比較の表によると、「品質」を80から40に変えたら、ファイルサイズは約半分になってます 「品質」設定は、結構ファイルサイズに効くようです 元画像(lena.jpg)の圧縮が、もし「品質」95よりもかなり小さい(高圧縮)数値相当の圧縮がされてるのなら、それに合わせて「品質」を設定して画像保存しないと、質問者さんが意図してるような結果にはなりませんよね
jbpb0

2022/09/29 06:51 編集

質問者さんが使ってる画像とは違うかもしれませんが、 http://icb-lab.naist.jp/members/yoshi/ouec_lecture/image_recognition/ の「演習教材」の「"Lena" image」の「len_std.jpg」 http://icb-lab.naist.jp/members/yoshi/ouec_lecture/image_recognition/image_files/len_std.jpg をダウンロードして、試してみました 以下、opencvのjpeg保存の「品質」を設定しない場合の、ファイルサイズ(byte)です ・元画像:11888 ・読み込んで保存(カラー):22611 ・読み込んでグレースケール変換して保存:19443 カラーのままでサイズが元画像の2倍くらいになってるので、グレースケールでもまだサイズ大きいですね 「品質」70で保存したら、カラーで保存した場合のファイルサイズがだいたい同じになりました ・元画像:11888 ・読み込んで保存(カラー):11973 ・読み込んでグレースケール変換して保存:10219 グレースケールのサイズは元画像の86%くらいになり、一応サイズは小さくなりましたが、 > 体感的に1-2割が限度と感じています。 ですね
tiqua_nibio

2022/09/29 07:17

情報ありがとうございます。 圧縮率ですが、大体の目安として 幅*高さ*3 とファイルサイズbyteを比較して、大きく離れているほど、圧縮されているという感じのようです。
guest

回答1

0

ベストアンサー

rgbの数値を入れる配列情報が残ったままになっているのでしょうか。

そうはなってないはずです
コードの最後に

python

1print(img.shape) 2print(img_gray.shape)

を追加して実行したら分かりますが、「img_gray」は次元が2次元に減ってます(カラー情報が無くなってます)

「cv2.imwrite()」では、データ(numpy配列)のshapeが「(縦, 横)」の場合はグレースケールで、「(縦, 横, 3)」の場合はカラーで保存されますので、「img_gray」を保存した「after_Lena.jpg」は、グレースケール画像のファイルのはずです

参考
Python, OpenCVで画像ファイルの読み込み、保存(imread, imwrite)
の「グレースケール(白黒)で読み込み、保存」の「cv2.imwrite()で画像ファイルに保存」

 
解像度(縦横の画素数)を変えずにカラーのままで保存した場合に、元の画像ファイルとサイズがだいたい同じになる「品質」(cv2.IMWRITE_JPEG_QUALITY)に設定しないと、

圧縮率はできるだけ上げない(拡大したときの画質を維持)

にはなりません
そのように「品質」を設定した上で、グレースケールで保存したら、ファイルのサイズは元画像よりも小さくなるでしょう

参考
Python, OpenCVで画像ファイルの読み込み、保存(imread, imwrite)
の「カラー(BGR)で読み込み、保存」の「cv2.imwrite()で画像ファイルに保存」

投稿2022/09/26 02:35

jbpb0

総合スコア7653

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

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

tiqua_nibio

2022/09/29 05:37

ありがとうございました。 opencvのデフォルトの圧縮率などが、少し強めになっているので、もともとの画像が圧縮されたものであれば、それを解像度を変更しない加工の後、別名保存したところで容量はあまり変わらなさそうですね。
jbpb0

2022/09/29 06:06

> opencvのデフォルトの圧縮率などが、少し強めになっている opencvでのjpeg保存の「品質」(大きいほど画質がいい=圧縮しない)は、範囲が0〜100で、指定しないと95だそうです 95は上限100に近いので、デフォルト設定では、圧縮はかなり控えめですよね https://tat-pytone.hatenablog.com/entry/2021/04/25/114334 上記Webページの、「品質」を変えて保存した画像ファイルのサイズ比較の表によると、「品質」を80から40に変えたら、ファイルサイズは約半分になってます 「品質」設定は、結構ファイルサイズに効くようです 元画像(lena.jpg)の圧縮が、もし「品質」95よりもかなり小さい(高圧縮)数値相当の圧縮がされてるのなら、それに合わせて「品質」を設定して画像保存しないと、質問者さんが意図してるような結果にはなりませんよね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問