0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クラウド開発環境PaizaCloudクラウドIDEでHello World(OpenCV編 その2)

Posted at

はじめに

今回の記事は以下の記事からの続きです。
クラウド開発環境PaizaCloudクラウドIDEでHello World(OpenCV編 その1)
前回の記事ではOpenCVの「前処理」の例を試してみました。今回のその続きの「解析」にあたる処理を試してみます。

今回の前提について

前回と同じですが、本記事では画像処理の理論そのものは扱いません。(※というか私ではうまく説明出来ません。)あくまで「入力 → ライブラリで処理 → 出力」という流れを体験することを目的にしています。

今回のプログラム

以下が今回のプログラムです。画像内の多角形を解析します。

detect_shapes.py
import cv2

# 1) 画像の読み込み
img = cv2.imread("shapes_sample.png")              # ← ここに同名で置く
if img is None:
    raise FileNotFoundError("shapes_sample.png が見つかりません")

# 2) グレースケール化(前処理)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite("step1_gray.png", gray)

# 3) 二値化(前処理)
#   彩色図形(赤/青/緑)はグレーにすると 30~150 程度の濃度になります。
#   図形を白(=前景)、背景を黒にしたいので BINARY_INV を使います。
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imwrite("step2_binary.png", binary)

# 4) 輪郭抽出(解析)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 5) 近似で頂点数を数える(解析)
out_contours = img.copy()
out_labeled  = img.copy()

def name_by_vertices(v):
    if v == 3:  return "Triangle"
    if v == 4:  return "Quadrilateral"
    if v == 5:  return "Pentagon"
    if v == 6:  return "Hexagon"
    # 7以上はだいたい円っぽいものとして
    return f"{v}-gon"

for cnt in contours:
    # 輪郭を簡略化(頂点を減らして近似): 0.02*周長 が定番の初期値
    epsilon = 0.02 * cv2.arcLength(cnt, True)
    approx  = cv2.approxPolyDP(cnt, epsilon, True)
    vertices = len(approx)

    # 輪郭の描画(緑)
    cv2.drawContours(out_contours, [cnt], -1, (0,255,0), 2)

    # ラベル描画用座標
    x, y, w, h = cv2.boundingRect(approx)
    label = name_by_vertices(vertices)

    # ラベルを重ねる(赤文字)
    cv2.putText(out_labeled, label, (x, y-8),
                cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,255), 2, cv2.LINE_AA)
    cv2.drawContours(out_labeled, [approx], -1, (0,255,0), 2)

# 6) 途中経過と結果の保存
cv2.imwrite("step3_contours.png", out_contours)    # 輪郭だけ描いた画像
cv2.imwrite("step4_labeled.png",  out_labeled)     # ラベル付き完成画像

print(f"検出した輪郭数: {len(contours)}")
print("保存しました: step1_gray.png, step2_binary.png, step3_contours.png, step4_labeled.png")

期待される判定(このサンプル画像)shapes_sample.png

  • 赤い三角形 → Triangle (3頂点)
  • 青い四角形 → Quadrilateral (4頂点)
  • 緑の五角形 → Pentagon (5頂点)

何が起きてるか(見る順番)

  • step1_gray.png
     カラーをグレーに。赤=76、青=29、緑=150、背景は255(白)くらいの濃度になります。
    step1_gray.png
  • step2_binary.png
     THRESH_BINARY_INV で 図形が白、背景が黒 に。輪郭抽出の前処理として扱いやすい形。
    step2_binary.png
  • step3_contours.png
     抽出した輪郭を緑で重ね描画。検出個数がコンソールにも出ます。(緑は重なっています)
    step3_contours.png
  • step4_labeled.png
     approxPolyDP の頂点数で Triangle / Quadrilateral / Pentagon をラベリング。
    step4_labeled.png

うまくいかない時の調整ポイント

  • 図形が欠ける/ギザギザ
    • 二値化を cv2.threshold(gray, しきい値, 255, cv2.THRESH_BINARY_INV) の しきい値 を 100〜160 で微調整
    • 事前に cv2.GaussianBlur(gray, (3,3), 0) で軽くノイズを抑えると安定
  • 頂点数が多すぎる/少なすぎる
    • epsilon = 0.02 * 周長 を 0.01〜0.03 に調整(数値を大きくすると頂点が減り、小さくすると増える)
  • 余計な小さなゴミ輪郭が混じる
    • cv2.contourArea(cnt) で面積が小さい輪郭をスキップ(例:面積 < 100 なら continue)

実行の手順(GUIなし環境)

shapes_sample.png を作業ディレクトリへ
上記のPythonプログラムをdetect_shapes.pyで画像ファイルと同じで作業ディレクトリに保存

ターミナルで実行

$ python deltect_shapes.py

PaizaCloudでの実行例
opencv1.png
輪郭(図形)を3つ認識して、出力ファイルが生成されています。

さいごに

今回はここまでです。前回と合わせて、OpenCVの前処理から解析の流れを簡単ではありますが試してみました。引き続きOpenCVも含めていろいろと投稿出来ればと思います。

ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?