如何找到图像中物体的方向?
How to find orientation of an object in image?
我有一堆齿轮图片,它们的方向都不同,我需要它们都在同一方向。我的意思是只有一张参考图像,其余图像应该旋转,这样它们看起来就和参考图像一样了。我遵循了这些步骤,首先将齿轮分段,然后尝试使用力矩找到一个角度,但它无法正常工作。我附上了 3 张图片,将第一张图片作为参考图片,这是目前的代码
def adjust_gamma(image, gamma=1.0):
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
return cv2.LUT(image, table)
def unsharp_mask(image, kernel_size=(13, 13), sigma=1.0, amount=2.5, threshold=10):
"""Return a sharpened version of the image, using an unsharp mask."""
blurred = cv2.GaussianBlur(image, kernel_size, sigma)
sharpened = float(amount + 1) * image - float(amount) * blurred
sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
sharpened = sharpened.round().astype(np.uint8)
if threshold > 0:
low_contrast_mask = np.absolute(image - blurred) < threshold
np.copyto(sharpened, image, where=low_contrast_mask)
return sharpened
def find_orientation(cont):
m = cv2.moments(cont, True)
cen_x = m['m10'] / m['m00']
cen_y = m['m01'] / m['m00']
m_11 = 2*m['m11'] - m['m00'] * (cen_x*cen_x+cen_y*cen_y)
m_02 = m['m02'] - m['m00'] * cen_y*cen_y
m_20 = m['m20'] - m['m00'] * cen_x*cen_x
theta = 0 if m_20==m_02 else atan2(m_11, m_20-m_02)/2.0
theta = theta * 180 / pi
return (cen_x, cen_y, theta)
def rotate_image(img, angles):
height, width = img.shape[:2]
rotation_matrix = cv2.getRotationMatrix2D((width/2, height/2), angles, 1)
rotated_image = cv2.warpAffine(img, rotation_matrix, (width,height))
return rotated_image
img = cv2.imread('gear1.jpg')
resized_img = imutils.resize(img, width=540)
height, width = resized_img.shape[:2]
gamma_adjusted = adjust_gamma(resized_img, 2.5)
sharp = unsharp_mask(gamma_adjusted)
gray = cv2.cvtColor(sharp, cv2.COLOR_BGR2GRAY)
gauss_blur = cv2.GaussianBlur(gray, (13,13), 2.5)
ret, thresh = cv2.threshold(gauss_blur, 250, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel, iterations=2)
kernel = np.ones((3,3), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[0]
cen_x, cen_y, theta = find_orientation(contours[0])
reference_angle = -24.14141919602858
rot_angle = 0.0
if theta < reference_angle:
rot_angle = -(theta - reference_angle)
else:
rot_angle = (reference_angle - theta)
rot_img = rotate_image(resized_img, rot_angle)
谁能告诉我哪里出错了?任何帮助将不胜感激。
齿轮和孔的二值化似乎很容易。您应该能够将孔洞与噪声和超小特征区分开来。
首先找到几何中心,围绕中心按角度对孔进行排序。还要计算孔的面积。然后你可以尝试以循环的方式将孔匹配到模型。有20个孔,你只需要测试20个位置。您可以通过角度和面积差异的某种组合来评价匹配。最佳匹配告诉你方向。
这个应该很靠谱
您可以通过计算每个孔的平均误差并校正以取消该值来获得非常准确的角度值(这相当于 least-squares 拟合)。
我有一堆齿轮图片,它们的方向都不同,我需要它们都在同一方向。我的意思是只有一张参考图像,其余图像应该旋转,这样它们看起来就和参考图像一样了。我遵循了这些步骤,首先将齿轮分段,然后尝试使用力矩找到一个角度,但它无法正常工作。我附上了 3 张图片,将第一张图片作为参考图片,这是目前的代码
def adjust_gamma(image, gamma=1.0):
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
return cv2.LUT(image, table)
def unsharp_mask(image, kernel_size=(13, 13), sigma=1.0, amount=2.5, threshold=10):
"""Return a sharpened version of the image, using an unsharp mask."""
blurred = cv2.GaussianBlur(image, kernel_size, sigma)
sharpened = float(amount + 1) * image - float(amount) * blurred
sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
sharpened = sharpened.round().astype(np.uint8)
if threshold > 0:
low_contrast_mask = np.absolute(image - blurred) < threshold
np.copyto(sharpened, image, where=low_contrast_mask)
return sharpened
def find_orientation(cont):
m = cv2.moments(cont, True)
cen_x = m['m10'] / m['m00']
cen_y = m['m01'] / m['m00']
m_11 = 2*m['m11'] - m['m00'] * (cen_x*cen_x+cen_y*cen_y)
m_02 = m['m02'] - m['m00'] * cen_y*cen_y
m_20 = m['m20'] - m['m00'] * cen_x*cen_x
theta = 0 if m_20==m_02 else atan2(m_11, m_20-m_02)/2.0
theta = theta * 180 / pi
return (cen_x, cen_y, theta)
def rotate_image(img, angles):
height, width = img.shape[:2]
rotation_matrix = cv2.getRotationMatrix2D((width/2, height/2), angles, 1)
rotated_image = cv2.warpAffine(img, rotation_matrix, (width,height))
return rotated_image
img = cv2.imread('gear1.jpg')
resized_img = imutils.resize(img, width=540)
height, width = resized_img.shape[:2]
gamma_adjusted = adjust_gamma(resized_img, 2.5)
sharp = unsharp_mask(gamma_adjusted)
gray = cv2.cvtColor(sharp, cv2.COLOR_BGR2GRAY)
gauss_blur = cv2.GaussianBlur(gray, (13,13), 2.5)
ret, thresh = cv2.threshold(gauss_blur, 250, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel, iterations=2)
kernel = np.ones((3,3), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[0]
cen_x, cen_y, theta = find_orientation(contours[0])
reference_angle = -24.14141919602858
rot_angle = 0.0
if theta < reference_angle:
rot_angle = -(theta - reference_angle)
else:
rot_angle = (reference_angle - theta)
rot_img = rotate_image(resized_img, rot_angle)
谁能告诉我哪里出错了?任何帮助将不胜感激。
齿轮和孔的二值化似乎很容易。您应该能够将孔洞与噪声和超小特征区分开来。
首先找到几何中心,围绕中心按角度对孔进行排序。还要计算孔的面积。然后你可以尝试以循环的方式将孔匹配到模型。有20个孔,你只需要测试20个位置。您可以通过角度和面积差异的某种组合来评价匹配。最佳匹配告诉你方向。
这个应该很靠谱
您可以通过计算每个孔的平均误差并校正以取消该值来获得非常准确的角度值(这相当于 least-squares 拟合)。