Python 画像処理

OpenCVによる画像表示

インストール

pip install opencv-python

画像の表示

image1.py に記述

import cv2
import os

# 画像の読み込み
path = os.path.dirname(__file__) + '/sample.jpg'
img = cv2.imread(path)

# 画像の表示
cv2.imshow('img', img)
cv2.waitKey(0)

画像の保存

path = os.path.dirname(__file__) + '/sample2.png'
cv2.imwrite(path, img)

加工

image2.pyに以下を記述

import cv2
import os

# 画像の読み込み
path = os.path.dirname(__file__) + '/sample.jpg'
img = cv2.imread(path)

# 画像の加工

# 画像の表示
cv2.imshow('img', img)
cv2.waitKey(0)

画像の加工のところに随時貼り付けていく。試したコードはコメントにして次を試す(Ctrl+/ でコメント化可能)。

サイズ変更

print(img.shape) # 現在のサイズ

400×400に変更

img = cv2.resize(img,(400,400)) # サイズ変更

切り抜き

[y1:y2, x1:x2]で左上x1,y1から右下x2,y2を切り抜く。

img = img[0:500, 100:400]  # 切り抜き 100,0 ~ 400,500

方向反転

img = cv2.flip(img, 0) # 上下反転
img = cv2.flip(img, 1) # 左右反転

ネガポジ反転

img = 255 - img # ネガポジ反転

グレイスケール

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # グレイスケール

ぼかし

img = cv2.blur(img, (10,10)) # ぼかし

一部分をぼかす(切り出し->ぼかし->合成)

img2 = img[0:500, 100:400]  # 切り出し
img2 = cv2.blur(img2, (10,10)) # ぼかし
img[0:500, 100:400] = img2 # 合成

しきい値処理

ある数(しきい値)より大きいドットを全て同じ色にする。

cv2.threshold(画像, しきい値, 置換後の値, 処理方法)

※処理方法はcv2.THRESH_BINARYが一般的
※戻り値はタプル。2つ目に画像が入る。

_,img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)

描画

image3.pyに以下を記述

import cv2
import os

# 画像の読み込み
path = os.path.dirname(__file__) + '/sample.jpg'
img = cv2.imread(path)

# 画像の描画

# 画像の表示
cv2.imshow('img', img)
cv2.waitKey(0)

画像の描画のところに随時貼り付けていく。試したコードはコメントにして次を試す(Ctrl+/ でコメント化可能)。

直線

# 直線 line(画像, 始点, 終点, 色, 線の太さ)
cv2.line(img, (100,100), (200,200), (0, 0, 255), 2)

※色はBGRの順に指定。上の例は赤

四角形

# 四角形 rectangle(画像, 左上, 右下, 色, 線の太さ)
cv2.rectangle(img, (100, 100), (200,200), (0, 0, 255), 2)

※線の太さはマイナスなら塗りつぶし

# 円 circle(画像, 中心, 半径, 色, 線の太さ)
cv2.circle(img, (200, 200), 100, (0, 0, 255), 2)

※線の太さはマイナスなら塗りつぶし

モザイク処理

関数を自作。一度小さくして大きくする。

def mosaic(img, rect, size):
    (x1, y1, x2, y2) = rect
    width = x2 - x1
    height = y2 - y1
	
    image_rect = img[y1:y2, x1:x2]
    image_small = cv2.resize(image_rect, (size, size))
    image_mos = cv2.resize(image_small, (width, height), interpolation=cv2.INTER_AREA)
	
    img2 = img.copy()
    img2[y1:y2, x1:x2] = image_mos
    
    return img2

img = mosaic(img, (100,100, 300,300), 10)

カメラからの入力

VideoCaptureオブジェクト

カメラからVideoCaptureオブジェクトの取得

cap = cv2.VideoCapture(カメラ番号, cv2.CAP_DSHOW)

最初の引数はカメラ番号。通常0から順に割り当てられる。

2番目の引数ではDirectSHOWオプションを指定する(Windows10以降では必須)。

メソッド

read()画像読み込み。タプルを返し、2番目が画像。
release()キャプチャ終了(カメラ解放)

カメラ入力を画像表示

camera.py に記述

import cv2

# カメラから入力開始
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

while True:
    # カメラの画像を読み込む
    result, frame = cap.read()
    
    # 画像を縮小
    frame = cv2.resize(frame, (500,300))
    
    # ウィンドウに画像を出力 
    cv2.imshow('Camera', frame)

    if cv2.waitKey(1) == 27:  # 1ミリ秒待ち。ESCキーで終了
        break

cap.release() # カメラを解放
cv2.destroyAllWindows() # ウィンドウを破棄

顔検出

face.py に記述

カスケードファイルを用意する。
人間の顔は haarcascade_frontalface_default.xml を入手(↓のボタンを押してダウンロードし、コピー)。

import cv2
import os

# 画像の読み込み
path = os.path.dirname(__file__)
img = cv2.imread(path + '/sample.jpg')

# グレイスケールに
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# カスケードファイルの読み込み
face_cascade = cv2.CascadeClassifier(path + '/haarcascade_frontalface_default.xml')

# 顔認証
faces = face_cascade.detectMultiScale(gray)

# 座標を取得
for (x, y, width, height) in faces:
    # 顔部分を四角で囲う
    cv2.rectangle(img, (x, y), (x+width, y+height), (255, 0, 0), 2)

cv2.imshow('img', img)
cv2.waitKey(0)

カメラによる認識

face_camera.py に記述

import cv2
import os

path = os.path.dirname(__file__)
face_cascade = cv2.CascadeClassifier(path + '/haarcascade_frontalface_default.xml')
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

while True:
   ret, img = cap.read()
   gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
   faces = face_cascade.detectMultiScale(gray)
   
   for (x, y, width, height) in faces:
      cv2.rectangle(img, (x, y), (x+width, y+height), (255, 0, 0), 2)
     	 
   cv2.imshow('camera', img)

   if cv2.waitKey(10) == 27:
      break

cap.release()
cv2.destroyAllWindows()

物体検出

YOLO v8を使用し画像内の物体を検出する。

準備

pip install ultralytics

物体検出

yolo1.py に記述

from ultralytics import YOLO
import cv2

# モデルの生成
model = YOLO('yolov8n.pt')

# 判定
results = model.predict('https://ultralytics.com/images/bus.jpg')
img = results[0].plot()

# 表示
cv2.imshow('img', img)
cv2.waitKey(0)

以下のように行うと /runs/detect/predice 配下に判定画像が格納される

yolo2.py に記述

from ultralytics import YOLO

# モデルの生成
model = YOLO('yolov8n.pt')

# 判定
model.predict('https://ultralytics.com/images/bus.jpg', save=True)

カメラによるリアルタイム判定

yolo_camera.py に記述

from ultralytics import YOLO
import cv2

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

model = YOLO("yolov8n.pt")

while True:
    success, img = cap.read()

    results = model.predict(img)
    frame = results[0].plot()

    cv2.imshow("YOLOv8", frame)
    
    if cv2.waitKey(5) == 27:
        break

検出できる物体

yolo3.py に記述

from ultralytics import YOLO

# モデルの生成
model = YOLO('yolov8n.pt')

# 物体検出できるものを表示
print(model.names)

結果

{0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus', 6: 'train', 7: 'truck', 8: 'boat', 9: 'traffic light', 10: 'fire hydrant', 11: 'stop sign', 12: 'parking meter', 13: 'bench', 14: 'bird', 15: 'cat', 16: 'dog', 17: 'horse', 18: 'sheep', 19: 'cow', 20: 'elephant', 21: 'bear', 22: 'zebra', 23: 'giraffe', 24: 'backpack', 25: 'umbrella', 26: 'handbag', 27: 'tie', 28: 'suitcase', 29: 'frisbee', 30: 'skis', 31: 'snowboard', 32: 'sports ball', 33: 'kite', 34: 'baseball bat', 35: 'baseball glove', 36: 'skateboard', 37: 'surfboard', 38: 'tennis racket', 39: 'bottle', 40: 'wine glass', 41: 'cup', 42: 'fork', 43: 'knife', 44: 'spoon', 45: 'bowl', 46: 'banana', 47: 'apple', 48: 'sandwich', 49: 'orange', 50: 'broccoli', 51: 
'carrot', 52: 'hot dog', 53: 'pizza', 54: 'donut', 55: 'cake', 56: 'chair', 57: 'couch', 58: 'potted plant', 59: 'bed', 60: 'dining table', 61: 'toilet', 62: 'tv', 63: 'laptop', 64: 'mouse', 65: 'remote', 66: 'keyboard', 67: 'cell phone', 68: 'microwave', 69: 'oven', 70: 'toaster', 71: 'sink', 72: 'refrigerator', 73: 'book', 74: 'clock', 75: 'vase', 76: 'scissors', 77: 'teddy bear', 78: 'hair drier', 79: 'toothbrush'}

predictを行う際にclassesを指定して物体検出できるものを絞り込むことができる

yolo3.py の下に記述

# personとcarのみ
results = model.predict('https://ultralytics.com/images/bus.jpg', classes=[0, 2])

# 表示
img = results[0].plot()

import cv2
cv2.imshow('img', img)
cv2.waitKey(0)

検出結果の取得

yolo4.py に記述

from ultralytics import YOLO
import cv2

# モデルの生成
model = YOLO('yolov8n.pt')

# 判定
results = model.predict('https://ultralytics.com/images/bus.jpg')

# 検出したオブジェクトの座標取得
for box in results[0].boxes:
    x1, y1, x2, y2 = [int(i) for i in box.xyxy[0]]
    print(f"StartX={x1}, StartY={y1}, EndX={x2}, EndY={y2}")