如何在python中居中二进制图像的内容/对象?

问题描述 投票:1回答:2

我有一个计算图形方向的代码。然后,根据此方向旋转图形,直到将其拉直。这一切都很好。我正在努力的是将旋转图形的中心移到整个图像的中心。因此,图形的中心点应与整个图像的中心点匹配。

输入图像:enter image description here

代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

path = "inputImage.png"


image=cv2.imread(path)
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh=cv2.threshold(gray,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]

contours,hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
cnt1 = contours[0]
cnt=cv2.convexHull(contours[0])
angle = cv2.minAreaRect(cnt)[-1]
print("Actual angle is:"+str(angle))
rect = cv2.minAreaRect(cnt)

p=np.array(rect[1])

if p[0] < p[1]:
        print("Angle along the longer side:"+str(rect[-1] + 180))
        act_angle=rect[-1]+180
else:
        print("Angle along the longer side:"+str(rect[-1] + 90))
        act_angle=rect[-1]+90
#act_angle gives the angle of the minAreaRect with the vertical

if act_angle < 90:
        angle = (90 + angle)
        print("angleless than -45")

        # otherwise, just take the inverse of the angle to make
        # it positive
else:
        angle=act_angle-180
        print("grter than 90")

# rotate the image to deskew it
(h, w) = image.shape[:2]
print(h,w)
center = (w // 2, h // 2)
print(center)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h),flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)

plt.imshow(rotated)
cv2.imwrite("rotated.png", rotated)

有输出:

enter image description here

如您所见,白色图形稍微偏左,我希望它完全居中。有谁知道该怎么做?

EDIT:我尝试了@joe的建议,并通过将图片的宽度和高度除以2从图像的中心减去了质心坐标。由此我得到了一个偏移量,必须对此进行添加到描述图像的数组。但是我不知道如何将偏移量添加到数组中。如何使用x和y坐标?

代码:

img = cv2.imread("inputImage")
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,127,255,0)

height, width = gray_image.shape
print(img.shape)
wi=(width/2)
he=(height/2)
print(wi,he)
M = cv2.moments(thresh)

cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])

offsetX = (wi-cX)
offsetY = (he-cY)


print(offsetX,offsetY)
print(cX,cY)
python numpy opencv image-processing centering
2个回答
1
投票

这是Python / OpenCV中的一种方法。

从轮廓获取白色区域的边界框。计算最近区域的偏移量。使用numpy切片将其复制到输入大小的黑色背景的中心。

输入:

enter image description here

import cv2
import numpy as np

# read image as grayscale
img = cv2.imread('white_shape.png', cv2.COLOR_BGR2GRAY)

# get shape
hh, ww = img.shape


# get contours (presumably just one around the nonzero pixels) 
contours = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
for cntr in contours:
    x,y,w,h = cv2.boundingRect(cntr)

# recenter
startx = (ww - w)//2
starty = (hh - h)//2
result = np.zeros_like(img)
result[starty:starty+h,startx:startx+w] = img[y:y+h,x:x+w]

# view result
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save reentered image
cv2.imwrite('white_shape_centered.png',result)

enter image description here


0
投票

一种方法是获取二进制对象的边界框坐标,然后使用Numpy切片来裁剪ROI。从这里我们计算新的偏移坐标,然后将ROI粘贴到新的空白蒙版上。

enter image description here

代码

import cv2
import numpy as np

# Load image as grayscale and obtain bounding box coordinates
image = cv2.imread('1.png', 0)
height, width = image.shape
x,y,w,h = cv2.boundingRect(image)

# Create new blank image and shift ROI to new coordinates
mask = np.zeros(image.shape, dtype=np.uint8)
ROI = image[y:y+h, x:x+w]
x = width//2 - ROI.shape[0]//2 
y = height//2 - ROI.shape[1]//2 
mask[y:y+h, x:x+w] = ROI

cv2.imshow('ROI', ROI)
cv2.imshow('mask', mask)
cv2.waitKey()
© www.soinside.com 2019 - 2024. All rights reserved.