空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

Hough変換で直線、円検出をやってみる

import cv2
import numpy as np

img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)

lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv2.imwrite('houghlines3.jpg',img)
  1. 第1引数は入力画像であり,2値画像でなければなりません.あらかじめ2値化やエッジ検出をした画像を使うと良いでしょう

  2. 第2,3引数にはそれぞれ \rho と \theta の精度を指定します.

  3. 第4引数は,直線とみなされるのに必要な最低限の投票数を意味するしきい値

確率的ハフ変換による直線検出

f:id:robonchu:20170821152747j:plain

import cv2
import numpy as np

img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,10,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv2.imwrite('houghlines.jpg',img)

f:id:robonchu:20170821152839j:plain

参考:ハフ変換による直線検出 — OpenCV-Python Tutorials 1 documentation

特徴検出 — opencv 2.2 documentation

円検出

f:id:robonchu:20170821162945j:plain

circles = cv2.HoughCircles(image, cv2.HOUGH_GRADIENT, dp=2, minDist=20, param1=20, param2=20, minRadius=6, maxRadius=20 )

パラメータ

dp ・・・ 処理するときに元画像の解像度の倍率.1だとそのままの画質で処理

minDist ・・・ 検出される円と円の最小距離

param1 ・・・ 低いほどいろんなエッジを検出

param2 ・・・ 低いほど円じゃないものも検出

minRadius ・・・ 最小半径

maxRadius ・・・ 最大半径

動作確認用雑なコード↓

import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while(1):
    # Take each frame
    _, frame = cap.read()

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    lower_light_pink = np.array([168, 50, 50])
    upper_light_pink = np.array([188, 255, 255])
    mask = cv2.inRange(hsv, lower_light_pink, upper_light_pink)

    circles = cv2.HoughCircles(mask,cv2.HOUGH_GRADIENT,1,20,
                                param1=50,param2=20,minRadius=0,maxRadius=0)

    if circles is None:
        cv2.imshow('frame',frame)
        k = cv2.waitKey(5) & 0xFF
        if k == 27:
            break
        pass
    else:
        circles = np.uint16(np.around(circles))

        circle = []
        x = []
        y = []

        for i in circles[0,:]:
            x.append(i[0])
            y.append(i[1])
            circle.append(i[2])

        idx = circle.index(max(circle))
        cv2.circle(frame,(x[idx],y[idx]),circle[idx],(0,255,0),2)
        cv2.imshow('frame',frame)
        k = cv2.waitKey(5) & 0xFF
        if k == 27:
            break

cv2.destroyAllWindows()

f:id:robonchu:20170821163010j:plain

所感

円検出のパラメータ調整難しい…

参考: 円の検出 - TB-code

Opencvの円検出についてOpencvで円検出をするのですが、表示された画像の、... - Yahoo!知恵袋

Python cv2.HoughCircles で円検出 – LLC DigiFie Good!

c++とframe rateの高いカメラを使えばもう少し円検出の速度が挙げれるみたい。。。