【CV2】： 画像とは何か、画像の明るさとコントラストを調整しよう

# PythonとOpenCVを使った画像操作の基本

PythonのCV2ライブラリでは、画像を読み込むとYとX座標に基づく2次元または3次元配列として保存されます。この配列は、`uint8`型（0から255までの8ビット符号なし整数）で構成され、画像の色や明るさを表します。この値に加えて、Red、Green、Blue（RGB）の3チャンネルで構成されることで、カラー画像が形成されます。

## なぜこの構造が重要なのか
画像を通常の配列のように操作（例: 配列を3で割る）すると、0から255の範囲外の値になる可能性があります。この結果、画像が正しく表示されなくなることがあります。したがって、このデータ構造を理解することは、正確に画像を操作するために非常に重要です。

## CV2で画像を表示する方法

以下のコードを使えば、簡単に画像を表示できます。

```python
# 必要ならopencv-pythonをインストールしてください
# pip install opencv-python
import cv2

# 画像を読み込む
image = cv2.imread('./test.png')

# 画像をウィンドウに表示
cv2.imshow('Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

![Image first test image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fk6rs7mt6v4rq6katzlk.png)

このコードを使うと、画像をポップアップウィンドウに表示できます。別の画像URLを指定してテストしてみてください。また、ズームインして画像のRGB値を確認することも可能です

![Image test image for zoom](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sxdz75xe4890nws78to5.png)


# 明るさとコントラストの調整
## 明るさとコントラストとは？
・明るさ (Brightness): 画像全体の明るさや暗さ。ピクセルの強度によって決まります。
・コントラスト (Contrast): ピクセル間の強度の差を指します。画像の「鮮明さ」や「際立ち具合」を測るものです。

明るさとコントラストを調整する基本式：` new_image = contrast × image + brightness`

## CV2で明るさとコントラストを調整する
OpenCVの`cv2.convertScaleAbs()`関数を使用すると、この調整が自動的に行えます。この関数は、ピクセル値が0から255の範囲内に収まるように調整します。

・`alpha`（コントラスト）: 通常0.0から3.0の範囲
・`beta`（明るさ）: 通常-100から100の範囲
以下は具体的なコード例です：

```python
image = cv2.imread('./test.png')
contrast = 0.8
brightness = 89
adjusted_image = cv2.convertScaleAbs(image, alpha=contrast, beta=brightness)
cv2.imshow('Adjustments', adjusted_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
```

![Image test image for brightens and contract change](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j2ifff8gehfs1gug27e1.png)

# インタラクティブな調整機能を作る
一度きりの調整も便利ですが、多くの場合、明るさやコントラストを動的に調整したいことがあります。この場合、OpenCVのトラックバー機能を使います。

トラックバーは、以下の構文で作成できます： `cv2.createTrackbar(trackbarname, winname, value, count, onChange_function)`

・`trackbarname`: トラックバーの名前
・`winname`: トラックバーを表示するウィンドウの名前
・`value`: 初期位置
・`count`: トラックバーの最大値
・`onChange_function`: トラックバー値が変更されたときに呼び出される関数
以下のコードで明るさとコントラストを動的に調整できます：
```python
def on_change(*args):
    alpha = cv2.getTrackbarPos('Contrast', 'Adjustments') / 10  # コントラスト [0.0, 3.0]
    beta = cv2.getTrackbarPos('Brightness', 'Adjustments') - 50  # 明るさ [-100, 100]
    updated_image = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
    cv2.imshow('Adjustments', updated_image)

# 画像を読み込む
image = cv2.imread('./test.png')
cv2.namedWindow('Adjustments')
cv2.imshow('Adjustments', image)

# トラックバーを追加
cv2.createTrackbar('Contrast', 'Adjustments', 10, 30, on_change)  # コントラスト
cv2.createTrackbar('Brightness', 'Adjustments', 50, 100, on_change)  # 明るさ

# 'x'キーで終了
while True:
    key = cv2.waitKey(1) & 0xFF
    if key == ord('x'):  # 'x'キーで終了
        print("Exiting...")
        break
cv2.destroyAllWindows()

```
![Image test finnl app image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cmaqzgjatoh9fv0fzw4e.png)

この関数は， `cv2.getTrackbarPos()` を用いてトラックバーの値を読み込みます．これらの値は， `cv2.convertScaleAbs` 関数を用いて画像に適用され，更新された画像がリアルタイムで表示されます．

このアプリをより使いやすくするために、最後に簡単なスニペットを追加して、ユーザが `x` キーを押すことで終了できるようにしました。これはOpenCVでよくある問題に対処するもので、ウィンドウを閉じてもコードの実行が止まるとは限らない。これを実装することで、このアプリはプロセスが長引かずにきれいに終了します。