在 Sobel 算子中实现角度约束
Implement angle constraint in the Sobel operator
我对这个问题中的边缘检测有几个疑问。
1) 我在下面写的代码试图只显示那些服从一定大小和方向约束的边缘。
当我使用 numpy 方法时,显示图像的 opencv 函数只显示黑色。
在 show_angle
函数中,当我使用 for
循环实现它并使用 cv2.imshow
.
显示图像时
然后我使用 numpy 方法检查输出,并使用返回 True
的 np.array_equal
我的 for 循环。
这背后的原因可能是什么?
2) 我无法处理角度限制,我会 post 一些不同角度限制的图像。
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()
输入图像:
图像直方图:
某些约束的输出:
0 到 90 度
90 到 180 度
谢谢。
好的,我发现错误了。
我的代码存在三个问题:
1) 在 show_angle
函数中,numpy 运算符应该进行大于等于和小于等于比较。
2) 我没有在用于将弧度转换为度的公式中除以 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)
我对这个问题中的边缘检测有几个疑问。
1) 我在下面写的代码试图只显示那些服从一定大小和方向约束的边缘。
当我使用 numpy 方法时,显示图像的 opencv 函数只显示黑色。
在 show_angle
函数中,当我使用 for
循环实现它并使用 cv2.imshow
.
然后我使用 numpy 方法检查输出,并使用返回 True
的 np.array_equal
我的 for 循环。
这背后的原因可能是什么?
2) 我无法处理角度限制,我会 post 一些不同角度限制的图像。
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()
输入图像:
图像直方图:
某些约束的输出:
0 到 90 度
90 到 180 度
谢谢。
好的,我发现错误了。
我的代码存在三个问题:
1) 在 show_angle
函数中,numpy 运算符应该进行大于等于和小于等于比较。
2) 我没有在用于将弧度转换为度的公式中除以 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)