送られてきた画像をWEBサイトに貼りたいんだけど、外周に枠が入っている…。
サイトの規約違反になるから枠を消したいんだけど、OpenCVでできる?
できますよ!
では今回は、「OpenCVで画像の枠を消す方法」を
できるだけわかりやすく解説いたします。
また、「複数の画像ファイルを一括で処理する方法」
も解説いたします。
ぜひ最後まで読んでいってください。
※わかりやすさを重視しております。厳密には解釈が異なる場合がありますことをご了承ください。
OpenCVで画像の枠を消す方法
OpenCVで画像の枠を消すには、2つの方法があります。
- 切り抜きする
- 上書きする
1つ1つ解説していきます。
まずは事前準備からご覧ください。
事前準備
- OpenCVのインストール
画像を加工したり編集したりするには「OpenCV」のインストールが必要です。
OpenCVを初めて使用する場合は、下記コードを入力・実行して、インストールしてください。
pip install opencv-python
※OpenCVを使用したことがある場合は、このインストール作業は不要です。
また本記事では「インポートや画像の読み込み・保存」といった基礎解説は割愛しております。
詳細を確認したい方は、下記記事をご参考ください。
では枠を消す方法を解説いたします。
切り抜きして枠を消す
まずは切り抜きして枠を消す方法です。
枠の内側を切り抜きします。
例えば画像が600×600pxで、外周の枠部分が5pxだったとします。
その場合、(5, 5)~(595, 595)までを切り抜きするというわけです。
切り抜きに関する詳しい解説は、下記記事をご参考ください。
それではコードをご覧ください。
import cv2
input_img = cv2.imread('C:/Utatane/input_img.jpg')
border = 5
height, width = input_img.shape[:2]
output_img = input_img[border : border, width-border : height-border]
cv2.imwrite('C:/Utatane/output_img.jpg', output_img)
border = 5
コードの5行目で、枠の太さを決めています。
まず新しい名前の変数を書いたら、「=(イコール)」を書きます。
変数名ですが、今回はborder(線)という名前にしましたが、何でも構いません。
しかしながら、名前の付け方には注意点があります。下記記事をご参考ください。
イコールの後ろには線の太さを書きます。
今回は「5px」にしていますが、枠を消したい画像を確認して決めてください。
私の経験上、枠の太さは1~3pxくらいが多かったので、5pxくらいにしておけば大丈夫かと思います。
height, width = input_img.shape[:2]
コードの6行目で元画像の「height(高さ)」と「width(横幅)」を取得しています。
「変数」「,(カンマ)」「変数」を書き、イコールを書きます。
そして、「枠を消したい画像が入った変数」に続けて「.shape[]」を書いてください。
[]内に「:(コロン)」と「2」を書いたら完了です。
【shape()とは】
「shape()」は画像の「高さ」「横幅」「色」を取得できるという便利なものです(色はカラー画像のみ)
今回は、直前に書いた「input_img」の「高さ」と「横幅」を取得しています。
取得した「高さ」と「横幅」は左辺の「height」と「width」にそれぞれ代入されます。
下記のようにすると、「高さ」「横幅」「色」の3つが取得できますが、今回「色」は必要ないので、取得していません。
height, width, color = input_img.shape[:3]
取得した「高さ」と「横幅」はコードの8行目で使用します。
output_img = input_img[border : border, width-border : height-border]
コードの8行目で画像を切り抜きしています。
コードの5行目で指定した「線の太さ」と、6行目で取得した「高さ」と「横幅」から切り抜く部分を決めています。
今回は、「border」には「5」、「width」と「height」にはそれぞれ「600」が入ります。
したがって、[5 : 5, 600-5 : 600-5]となり、(5, 5)~(595, 595)までが切り抜かれます。
これで枠を消すことができました。
切り抜きして枠を消す場合の注意点
切り抜きして枠を消す方法は非常に簡単な反面、デメリットがあります。
それは、枠を消した後の画像が元画像より小さくなるということです。
枠の内側をトリミングするので、当然ですね。
もし画像が小さくなるのが嫌な方は次に紹介する方法を試してみてください。
上書きして枠を消す
次に、上書きして枠を消す方法を紹介いたします。
「黒い枠線」の上に「白い枠線」を上書きして消すという具合です。
import cv2
input_img = cv2.imread('C:/Utatane/input_img.jpg')
border = 10
height, width = input_img.shape[:2]
cv2.line(input_img, (0, 0), (width, 0), (255, 255, 255), thickness=border)
cv2.line(input_img, (0, 0), (0, height), (255, 255, 255), thickness=border)
cv2.line(input_img, (width, 0), (width, height), (255, 255, 255), thickness=border)
cv2.line(input_img, (0, height), (width, height), (255, 255, 255), thickness=border)
cv2.imwrite('C:/Utatane/output_img.jpg', input_img)
8~11行目のみ解説いたします。
5・6行目は前項をご参考ください。
cv2.line(input_img, (0, 0), (width, 0), (255, 255, 255), thickness=border)
cv2.line(input_img, (0, 0), (0, height), (255, 255, 255), thickness=border)
cv2.line(input_img, (width, 0), (width, height), (255, 255, 255), thickness=border)
cv2.line(input_img, (0, height), (width, height), (255, 255, 255), thickness=border)
上記コードにて、上側・左側・右側・下側に白い線を追加しています。
まず、「cv2.line()」を書きます。
()内の引数に、「枠を消したい画像が入った変数」「線の始点の座標」「線の終点の座標」「線の色」「線の太さ」を指定します。
コードの8行目だけ詳しく見ていきましょう。
これは、画像の上側に白い線を追加した例です。
線の始点が(0,0)で、線の終点が(width,0)です。
「width」はコードの6行目で取得した画像の横幅ですので、今回は「600」が入ります。
したがって、線の始点は画像の左上(0,0)、線の終点は画像の右上(600,0)となり、画像の上側に白い線が引かれます。
色は(B,G,R)全てを255にすることで、白色を指定しています。
※背景の色に応じて変更してください。
線の太さですが、今回は「10」にしました。
実際の線の太さより大きい値(倍くらい)にするのが無難です。
同様にコード9~11行目で、「左側」「右側」「下側」にも白い線を追加することで、枠を消すことができます。
複数の画像を一括で処理する方法
フォルダにある全ての画像の枠を消すこともできます。
下記コードはfor文を使ってフォルダ内にある全ての画像の枠を消した例です。
今回はより簡単な「切り抜きする方法」で枠を消しています。
import cv2
import os
os.makedirs('C:/Utatane/output', exist_ok=True)
border = 5
for filename in os.listdir('C:/Utatane'):
if filename.endswith('.jpg') :
input_img = cv2.imread(os.path.join('C:/Utatane', filename))
height, width = input_img.shape[:2]
output_img = input_img[border : height-border, border : width-border]
cv2.imwrite(os.path.join('C:/Utatane/output', filename), output_img)
ざっくりと解説いたします。
<コード4行目>
出力するフォルダを作成
<コード8行目~最後>【for文でファイルが無くなるまでループ】
8行目:取り込みフォルダ内のファイルを取り込み
9行目:拡張子が「jpg」なら以下の操作を行う
10行目:取り込みフォルダのパスとファイル名を連結(フルパスに)して取り込み
11行目:画像のサイズを取得
12行目:枠線の内側を切り抜き
13行目:出力フォルダパスとファイル名を連結(フルパスに)して出力
これでフォルダ内の画像すべての枠を消すことができます。
うまく動作しない場合の対処法
画像の読み込みができない
画像ファイルが存在しない場合や、ファイルが破損している場合などは画像の読み込みができません。
画像を読み込み・保存する方法の記事を参考に、再度確認してください。
画像が保存されない
存在しないフォルダを指定した場合、画像は保存されません。
画像を読み込み・保存する方法の記事を参考に、再度確認してください。
エラーが出る
No module named ‘cv2’
これは、OpenCVがインストールできていない場合に出るエラーです。
事前準備の項を参考に、OpenCVのインストールを完了させてください。
OpenCV(4.10.0) ~ img.empty() ~
画像の読み込みが正常に行えていない可能性があります。
画像を読み込み・保存する方法の記事を参考に、画像のパスや形式を確認してください。
○○ is not defined
今まで出てきていない変数などを処理しようとした時に出るエラーです。
変数名などが間違っていないかチェックしましょう。
詳しい解説は、下記記事をご参考ください。
その他のエラー
その他のエラーが出た場合は、エラー文をコピーしてNETで検索してみましょう。
最後に
OpenCVで画像の枠を消す方法を解説いたしました。
当ブログでは、Pythonに関する情報を配信しております。
この記事がわかりやすいと感じた方は、他の記事も読んでいってください。
挫折せずにPythonを独学で学習する方法は特におすすめです。
最後までお読みいただき、ありがとうございました。がんばってください!