Skip to content Skip to sidebar Skip to footer

How To Center The Content/object Of A Binary Image In Python?

I have a code that computes the orientation of a figure. Based on this orientation the figure is then rotated until it is straightened out. This all works fine. What I am strugglin

Solution 1:

Here is one way in Python/OpenCV.

Get the bounding box for the white region from the contours. Compute the offset for the recentered region. Use numpy slicing to copy that to the center of a black background the size of the input.

Input:

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

Solution 2:

One approach is to obtain the bounding box coordinates of the binary object then crop the ROI using Numpy slicing. From here we calculate the new shifted coordinates then paste the ROI onto a new blank mask.

enter image description here

Code

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()

Solution 3:

@NawinNarain, from this point onwards where you found out the relative shifts w.r.t. centroid of the image, it is very straightforward - You want to make an Affine matrix with this translations and apply cv2.warpAffine() to your image. That's -it.

T = np.float32([[1, 0, shift_x], [0, 1, shift_y]]) 

We then use warpAffine() to transform the image using the matrix, T

centered_image = cv2.warpAffine(image, T, (orig_width, orig_height))

This will transform your image so that the centroid is at the center. Hope this helps. The complete center image function will look like this:

def center_image(image):
  height, width = image.shape
  print(img.shape)
  wi=(width/2)
  he=(height/2)
  print(wi,he)

  ret,thresh = cv2.threshold(image,95,255,0)

  M = cv2.moments(thresh)

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

  offsetX = (wi-cX)
  offsetY = (he-cY)
  T = np.float32([[1, 0, offsetX], [0, 1, offsetY]]) 
  centered_image = cv2.warpAffine(image, T, (width, height))

  return centered_image

Post a Comment for "How To Center The Content/object Of A Binary Image In Python?"