Python演習_01_OpenCV①

## はじめに
動作確認は下記環境で行っています

・OS: Windows11 Pro (64bit)
・Anaconda Navigator: 2.6.3
・Python: 3.10.16
・UI: jupyter Notebook 7.3.2
・OpenCV: 4.11.0
・サンプル画像：zophie.png（猫の写真）



### 1. OpenCVのインストール
Terminalにて
```ruby:
pip install opencv-python
```

【参考】バージョン指定の場合（例）
```ruby:
pip install opencv-python==4.8.0.76
```




## 2. 基本サンプル
#### バージョン確認
```ruby:
import cv2

print("OpenCV version")
print(cv2.__version__)
```

#### 画像の読み込みと表示

```ruby:
# 画像を読み込み
def read_img(image_path):
    # 指定されたパスから画像を読み込む
    image = cv2.imread(image_path)
    return image

# 画像を表示
def display_img(window_name,image):
    # 画像表示用のウィンドウを作成して表示 
    # ウインドウ名:window_name / 表示データ:image
    cv2.imshow(window_name, image)
    # キーが押されるまでウィンドウを保持
    cv2.waitKey(0)
    # ウィンドウを閉じてリソースを解放
    cv2.destroyAllWindows()

if __name__ == "__main__":
    image_path = './zophie.png'
    image = read_img(image_path)
    display_img('image',image)

```

#### グレースケール変換
```ruby:
import cv2

# 画像を読み込み
def read_img(image_path):
    image = cv2.imread(image_path)
    return image

# 画像を表示
def display_img(window_name,image):
    cv2.imshow(window_name, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 画像をグレースケールに変換
def convert_to_grayscale(image):
    # 画像(image)をBGRからグレースケールに変換
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return gray_image

if __name__ == "__main__":
    image_path = './zophie.png'
    image = read_img(image_path)
    gray_image = convert_to_grayscale(image)
    display_img('gray_image',gray_image)
```


#### リサイズ
```ruby:
import cv2

# 画像を読み込み
def read_img(image_path):
    image = cv2.imread(image_path)
    return image

# 画像を表示
def display_img(window_name,image):
    cv2.imshow(window_name, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 画像を指定されたサイズにリサイズ
def resize_img(image, width, height):
    # 画像(image)を指定された幅(width)と高さ(height)にリサイズ
    resized_image = cv2.resize(image, (width, height))
    return resized_image

if __name__ == "__main__":
    image_path = './zophie.png'
    image = read_img(image_path)
    # width:200px, height:200pxを指定
    resized_image = resize_img(image, 200, 200)
    display_img('resized_image',resized_image)
```


#### 回転
```ruby:
import cv2

# 画像を読み込み
def read_img(image_path):
    image = cv2.imread(image_path)
    return image

# 画像を表示
def display_img(window_name,image):
    cv2.imshow(window_name, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def rotate_img(image, angle):
    # 画像の高さと幅を取得
    (h, w) = image.shape[:2]
    # 画像の中心座標を計算 (//は切り捨て割算)
    center = (w // 2, h // 2)
    # 回転行列を生成
    # (center: 回転の中心, angle: 回転角度(反時計回り), scale: スケール(1.0で元のサイズ))
    matrix = cv2.getRotationMatrix2D(center, angle, scale=1.0)
    # アフィン変換を使って画像を回転
    rotated_image = cv2.warpAffine(image, matrix, (w, h))
    return rotated_image

if __name__ == "__main__":
    image_path = './zophie.png'
    image = read_img(image_path)
    # angle:20°を指定
    rotated_image = rotate_img(image, 20)
    display_img('rotated_image', rotated_image)
```

#### エッジ検出
```ruby:
import cv2

# 画像を読み込み
def read_img(image_path):
    image = cv2.imread(image_path)
    return image

# 画像を表示
def display_img(window_name,image):
    cv2.imshow(window_name, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 画像をグレースケールに変換
def convert_to_grayscale(image):
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return gray_image

# エッジ検出
def detect_edges(image):
    # 画像をグレースケールに変換
    gray_image = convert_to_grayscale(image)
    # Cannyアルゴリズムを使用してエッジを検出
    # (threshold1: 最小閾値, threshold2: 最大閾値)
    edges = cv2.Canny(gray_image, threshold1=100, threshold2=200)
    return edges

if __name__ == "__main__":
    image_path = './zophie.png'
    image = read_img(image_path)
    edges = detect_edges(image)
    display_img('edges', edges)
```

#### 猫の顔検出
```ruby:
import cv2

# 画像を読み込み
def read_img(image_path):
    image = cv2.imread(image_path)
    return image

# 画像を表示
def display_img(window_name,image):
    cv2.imshow(window_name, image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 画像をグレースケールに変換
def convert_to_grayscale(image):
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return gray_image

# エッジ検出
def detect_faces(image):
    # Haarカスケード分類器を読み込み
    # 顔検出用の事前学習済みカスケードファイルを指定
    #face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalcatface.xml')

    
    # 画像をグレースケールに変換
    gray_image = convert_to_grayscale(image)
    # 顔を検出 (scaleFactor: 画像サイズを縮小する比率,
    # minNeighbors: 顔とみなす領域に含まれる最小の矩形数, minSize: 検出される顔の最小サイズ)
    faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=2, minSize=(20, 20))
    # 顔が検出された部分に枠を描画するために元画像(image)を新たな画像(faces_image)にコピー
    faces_image = image
    # 顔が検出された部分に枠を描画
    for (x, y, w, h) in faces:
        # 青い矩形を描画
        cv2.rectangle(faces_image, (x, y), (x+w, y+h), (255, 0, 0), 2)
    return faces_image

if __name__ == "__main__":
    image_path = './zophie.png'
    image = read_img(image_path)
    faces_image = detect_faces(image)
    display_img('faces_image', faces_image)
```

#### 画像の保存
```ruby:
cv2.imwrite('output_image.png', image)
```






## 3. 演習課題
### 課題①
##### 読み込んだ画像をグレースケール変換してリサイズして回転して表示するプログラムを作成して下さい．


### 課題②
##### 課題①のプログラムにおいて，拡大縮小率と回転角度を任意に設定できる（ユーザーがキーボード入力）するプログラムを作成して下さい．



### 課題③
##### ネコの顔検出プログラムを人の顔を検出するプログラムに変更し，何人検出されたか（数字）を画面上に表示するプログラムを作成して下さい．


### 課題④
##### 下記の描画機能を使って絵を描いて下さい（使い方について自分で調べる練習）
・線分を描画: cv2.line()
・矢印を描画: cv2.arrowedLine()
・長方形を描画: cv2.rectangle()
・円を描画: cv2.circle()
・楕円を描画: cv2.ellipse()
・円弧を描画: cv2.ellipse()
・マーカーを描画: cv2.drawMarker()
・折れ線、多角形を描画: cv2.polylines(), cv2.fillPoly(),　fillConvexPoly()


### 課題⑤
##### それでも時間があまった場合はユーザーインターフェースを作成してみましょう