2016-11-08 31 views
0

在這個問題中,我有一些與邊緣檢測相關的疑問。在Sobel運算符中實現角度約束

1)我在下面寫的代碼試圖只顯示那些服從一定大小和方向約束的邊。 當我使用numpy方法時,顯示圖像的opencv函數只顯示黑色。 在show_angle函數中,當我使用for循環實現它時,使用cv2.imshow顯示圖像。

然後我使用numpy方法檢查輸出,並使用np.array_equal返回True。 背後的原因是什麼?

2)我不能工作的角度約束,我會張貼幾個圖像不同的角度約束。

import cv2 

import numpy as np 

import matplotlib.pyplot as plt 

def show_image(name, img, waitkey=0): 
    cv2.namedWindow(name, 0) 
    cv2.imshow(name, img) 
    cv2.waitKey(waitkey) 
    cv2.destroyWindow(name) 

img = cv2.imread('hex2.png') 
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

shape = img.shape 

out_x = cv2.Sobel(img, cv2.CV_16S, 1, 0) # x gradient 
out_y = cv2.Sobel(img, cv2.CV_16S, 0, 1) # y gradient 


out_x = cv2.convertScaleAbs(out_x) 
out_y = cv2.convertScaleAbs(out_y) 

out_weight = cv2.addWeighted(out_x, 0.5, out_y, 0.5,0) # x and y weighted 


def show_angle(out_weight, mag_final, dir_final, min_mag, theta_min, theta_max): 
    """ 
     Return points based on magnitude and angle constraints 
    """ 


    out_img = np.multiply(
     (
      (mag_final > min_mag) & 
      (dir_final > theta_min) & 
      (dir_final < theta_max) 
     ).astype(int), 

     out_weight 
    ) 

    return out_img 

def mag_dir(): 
    """ 
    Calculate gradient magnitude and direction matrix 
    """ 

    mag = np.sqrt(
       np.add 
        (
        np.square(out_x) , np.square(out_y) 
        ) 
       ) 

    dir = np.arctan2(out_y, out_x) 

    dir = np.multiply(dir, 180) 

    print np.min(dir) # 0 
    print np.max(dir) # 282 

    plt.hist(dir,8, (0,360)) 
    plt.show() 

    return mag, dir 

mag, dir = mag_dir() 



out_img = show_angle(out_weight, mag, dir, 0, 90,120) 

plt.imshow(out_img, cmap='gray') 
plt.show() 

輸入圖像:

hexagon image

圖像直方圖:

Image histogram for the hexagon.

輸出,用於一些約束:

0至90度

0 to 90 degrees

90度至180度

90 to 180 degrees

感謝。

+0

Didnt檢查代碼,但我的直覺:你不要忽視0(或接近於0)值像素。在你的圖像中,幾乎所有的背景都將具有幅度和角度0,因此可能是填充直方圖的0-45度框的像素。如果這不是你的問題,試試'np.multiply(dir,180/pi)'來獲得pi = 3.14159265359的角度度數... – Micka

+0

@Micka感謝你的幫助,我犯了一些錯誤,我糾正它們。第二個問題已解決,但我仍然無法使用'cv2.imshow'顯示圖像,原因可能是什麼。 – formatkaka

回答

0

好吧,我發現了錯誤。

有三個問題,我的代碼:

1)在show_angle功能numpy的運營商應該有比等於和小於或等於比較大。

2)在用於將rads轉換爲度數的公式中,我沒有除以pi

3)我應該將numpy矩陣轉換爲uint8類型。

改正的代碼:

import cv2 

import numpy as np 

import matplotlib.pyplot as plt 

import math 

def show_image(name, img, waitkey=0): 
    cv2.namedWindow(name, 0) 
    cv2.imshow(name, img) 
    cv2.waitKey(waitkey) 
    cv2.destroyWindow(name) 

img = cv2.imread('hex2.png') 
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

shape = img.shape 

out_x = cv2.Sobel(img, cv2.CV_16S, 1, 0) # x gradient 
out_y = cv2.Sobel(img, cv2.CV_16S, 0, 1) # y gradient 


out_x = cv2.convertScaleAbs(out_x) 
out_y = cv2.convertScaleAbs(out_y) 

out_weight = cv2.addWeighted(out_x, 0.5, out_y, 0.5,0) # x and y weighted 


def show_angle(out_weight, mag_final, dir_final, min_mag, theta_min, theta_max): 
    """ 
     Return points based on magnitude and angle constraints 
    """ 


    out_img = np.multiply(
     (
      # (mag_final > min_mag) & 
      (dir_final >= theta_min) & 
      (dir_final <= theta_max) 
     ).astype(int), 

     out_weight 
    ).astype('uint8') 

    return out_img 

def mag_dir(): 
    """ 
    Calculate gradient magnitude and direction matrix 
    """ 

    mag = np.sqrt(
       np.add 
        (
        np.square(out_x) , np.square(out_y) 
        ) 
       ) 

    dir = np.arctan2(out_y, out_x) 

    dir = np.multiply(dir, 180/math.pi) 

    print np.min(dir) # 0 
    print np.max(dir) # 89 

    # plt.hist(mag,8) 
    # plt.show() 

    return mag, dir 

mag, dir = mag_dir() 


out_final = show_angle(out_weight, mag, dir, 1, 60, 90) 
show_image("angle", out_final, 0)