2017-03-10 49 views
2

OpenCVで画像内のベッドを検出しようとしている。私は通常のグレースケール、ぼかし、Cannyを実行しています。私はConvex Hullを試しました。しかし、余分な輪郭を与え、オブジェクトの検出を混乱させるかなりの数の「ノイズ」があるので。このため、私はベッドを適切に検出することができません。Python OpenCV - 輪郭点の集合から最大の矩形を外挿する。

Results

あなたが見ることができるように、それはほとんどあります:

ここで入力された画像だけでなく、キャニーエッジ検出結果があります。私はベッドの輪郭を既に持っていますが、右上隅には隙間があり、閉じた長方形を検出できません。ベッドの輪郭が閉じていないので、私は長方形に合わせたり、最大面積の輪郭を検出することはできません

import cv2 
import numpy as np 

def contoursConvexHull(contours): 
    print("contours length = ", len(contours)) 
    print("contours length of first item = ", len(contours[1])) 
    pts = [] 
    for i in range(0, len(contours)): 
     for j in range(0, len(contours[i])): 
      pts.append(contours[i][j]) 

    pts = np.array(pts) 

    result = cv2.convexHull(pts) 

    print(len(result)) 
    return result 

def auto_canny(image, sigma = 0.35): 
    # compute the mediam of the single channel pixel intensities 
    v = np.median(image) 

    # apply automatic Canny edge detection using the computed median 
    lower = int(max(0, (1.0 - sigma) * v)) 
    upper = int(min(255, (1.0 + sigma) *v)) 
    edged = cv2.Canny(image, lower, upper) 

    # return edged image 
    return edged 


# Get our image in color mode (1) 
src = cv2.imread("bed_cv.jpg", 1) 

# Convert the color from BGR to Gray 
srcGray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) 

# Use Gaussian Blur 
srcBlur = cv2.GaussianBlur(srcGray, (3, 3), 0) 

# ret is the returned value, otsu is an image 
##ret, otsu = cv2.threshold(srcBlur, 0, 255, 
##       cv2.THRESH_BINARY+cv2.THRESH_OTSU) 

# Use canny 
##srcCanny = cv2.Canny(srcBlur, ret, ret*2, 3) 
srcCanny1 = auto_canny(srcBlur, 0.70) 

# im is the output image 
# contours is the contour list 
# I forgot what hierarchy was 
im, contours, hierarchy = cv2.findContours(srcCanny1, 
              cv2.RETR_TREE, 
              cv2.CHAIN_APPROX_SIMPLE) 

##cv2.drawContours(src, contours, -1, (0, 255, 0), 3) 

ConvexHullPoints = contoursConvexHull(contours) 
##cv2.polylines(src, [ConvexHullPoints], True, (0, 0, 255), 3) 

cv2.imshow("Source", src) 
cv2.imshow("Canny1", srcCanny1) 

cv2.waitKey(0) 

は、ここで私が実行しているコードです。

私が考えることができる解決策は、その小さなギャップをブリッジすることを期待して輪郭点を使用して可能な限り大きな矩形を外挿することですが、矩形が不完全であるために進める方法があまりわかりません。

ご協力いただければ幸いです。

+0

あなたは、エッジのライン検出を試みている画像を検出しました。私は同じことをしましたが、正確ではありません –

+0

ここでは他にどのようなユースケースがありますか?ベッドの色が変わっていますか?将来のデータによって生じる制限は何ですか? – m3h0w

+0

@JeruLuke私は、私が得ようとしている行を進める方法がわからないので、私は持っていません。 – Razgriz

答えて

4

あなたは他の例を提供していないので、私はこのケースで動作するアルゴリズムを提供します。しかし、他のサンプルの明るさや背景の変化に適応させる方法を見つけなければならないことに気をつけてください。

ノイズが多く、ダイナミックレンジが比較的大きいので、Cannyを使用せず、その代わりにAdaptive ThresholdingとFind Contoursを使用することをお勧めします(入力としてエッジを必要としません)。画像の異なる部分のための異なる閾値。

マイ結果:

enter image description here

はコード:

import cv2 
import numpy as np 

def clahe(img, clip_limit=2.0, grid_size=(8,8)): 
    clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=grid_size) 
    return clahe.apply(img) 

src = cv2.imread("bed.png") 

# HSV thresholding to get rid of as much background as possible 
hsv = cv2.cvtColor(src.copy(), cv2.COLOR_BGR2HSV) 
lower_blue = np.array([0, 0, 120]) 
upper_blue = np.array([180, 38, 255]) 
mask = cv2.inRange(hsv, lower_blue, upper_blue) 
result = cv2.bitwise_and(src, src, mask=mask) 
b, g, r = cv2.split(result) 
g = clahe(g, 5, (3, 3)) 

# Adaptive Thresholding to isolate the bed 
img_blur = cv2.blur(g, (9, 9)) 
img_th = cv2.adaptiveThreshold(img_blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
           cv2.THRESH_BINARY, 51, 2) 

im, contours, hierarchy = cv2.findContours(img_th, 
              cv2.RETR_CCOMP, 
              cv2.CHAIN_APPROX_SIMPLE) 

# Filter the rectangle by choosing only the big ones 
# and choose the brightest rectangle as the bed 
max_brightness = 0 
canvas = src.copy() 
for cnt in contours: 
    rect = cv2.boundingRect(cnt) 
    x, y, w, h = rect 
    if w*h > 40000: 
     mask = np.zeros(src.shape, np.uint8) 
     mask[y:y+h, x:x+w] = src[y:y+h, x:x+w] 
     brightness = np.sum(mask) 
     if brightness > max_brightness: 
      brightest_rectangle = rect 
      max_brightness = brightness 
     cv2.imshow("mask", mask) 
     cv2.waitKey(0) 

x, y, w, h = brightest_rectangle 
cv2.rectangle(canvas, (x, y), (x+w, y+h), (0, 255, 0), 1) 
cv2.imshow("canvas", canvas) 
cv2.imwrite("result.jpg", canvas) 
cv2.waitKey(0) 
関連する問題