Python: image center of array
Using skimage library I have to centralize images like these. I found SimilarityTransform
one that should accept offsets, but documentation is lacking. How can I determine the corners of such an image and then figure out how to center it? Arrays always exist from 28x28 images. Some images have noise in them, as does the second image here, which is four. I accidentally captured two very centered images, but they could be all over the array. You can also see a more visual representation below 4.
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 203 229 32 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 47 47 30 95 254 215 13 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 45 154 185 185 223 253 253 133 175 255 188 19 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 110 253 253 253 246 161 228 253 253 254 92 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 128 245 253 158 137 21 0 48 233 253 233 8 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 139 254 223 25 0 0 36 170 254 244 106 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 55 212 253 161 11 26 178 253 236 113 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 7 155 253 228 80 223 253 253 109 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 141 253 253 253 254 253 154 29 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 110 253 253 253 254 179 38 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 3 171 254 254 254 179 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 171 253 253 253 253 178 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 26 123 254 253 203 156 253 200 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 93 253 254 121 13 93 253 158 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 64 239 253 76 8 32 219 253 126 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 133 254 191 0 5 108 234 254 106 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 132 253 190 5 85 253 236 154 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 153 253 169 192 253 253 77 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 112 253 253 254 236 129 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 17 118 243 191 113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
[[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 164 252 63 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 23 34 0 244 254 112 0 0 0 0 85 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 4 190 225 0 255 185 13 0 0 0 0 95 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 6 170 254 197 64 254 59 0 0 0 0 0 95 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 9 132 254 204 23 112 254 28 0 0 0 0 0 77 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 6 167 254 216 58 24 242 225 16 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 76 254 254 162 85 138 254 188 0 0 0 48 85 25 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 3 159 254 254 254 254 254 228 151 151 214 250 254 75 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 7 79 131 158 254 254 226 225 225 225 190 148 39 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 127 254 148 0 0 0 0 0 0 0 71 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 23 248 201 0 0 0 0 0 0 0 0 36 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 85 254 118 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 12 189 227 22 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 114 254 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 44 226 175 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 148 203 59 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 26 242 140 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 131 169 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 19 233 65 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 174 109 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
SOLUTION CODE: Slightly modified the code provided by @anmol_uppal.
def pad_image(img, pad_t, pad_r, pad_b, pad_l):
"""Add padding of zeroes to an image.
Add padding to an array image.
:param img:
:param pad_t:
:param pad_r:
:param pad_b:
:param pad_l:
"""
height, width = img.shape
# Adding padding to the left side.
pad_left = np.zeros((height, pad_l), dtype = np.int)
img = np.concatenate((pad_left, img), axis = 1)
# Adding padding to the top.
pad_up = np.zeros((pad_t, pad_l + width))
img = np.concatenate((pad_up, img), axis = 0)
# Adding padding to the right.
pad_right = np.zeros((height + pad_t, pad_r))
img = np.concatenate((img, pad_right), axis = 1)
# Adding padding to the bottom
pad_bottom = np.zeros((pad_b, pad_l + width + pad_r))
img = np.concatenate((img, pad_bottom), axis = 0)
return img
def center_image(img):
"""Return a centered image.
:param img:
"""
col_sum = np.where(np.sum(img, axis=0) > 0)
row_sum = np.where(np.sum(img, axis=1) > 0)
y1, y2 = row_sum[0][0], row_sum[0][-1]
x1, x2 = col_sum[0][0], col_sum[0][-1]
cropped_image = img[y1:y2, x1:x2]
zero_axis_fill = (images[0].shape[0] - cropped_image.shape[0])
one_axis_fill = (images[0].shape[1] - cropped_image.shape[1])
top = zero_axis_fill / 2
bottom = zero_axis_fill - top
left = one_axis_fill / 2
right = one_axis_fill - left
padded_image = pad_image(cropped_image, top, left, bottom, right)
return padded_image
# Usage is in a for loop that iterates through 60.000 images.
for item in permuList:
shuImages.append(center_image(images[item]).reshape((28 * 28)))
source to share
img = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 203, 229, 32, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 47, 47, 30, 95, 254, 215, 13, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 154, 185, 185, 223, 253, 253, 133, 175, 255, 188, 19, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 253, 253, 253, 246, 161, 228, 253, 253, 254, 92, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 245, 253, 158, 137, 21, 0, 48, 233, 253, 233, 8, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, 254, 223, 25, 0, 0, 36, 170, 254, 244, 106, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 212, 253, 161, 11, 26, 178, 253, 236, 113, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 155, 253, 228, 80, 223, 253, 253, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, 253, 253, 253, 254, 253, 154, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 253, 253, 253, 254, 179, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 171, 254, 254, 254, 179, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 253, 253, 253, 253, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 26, 123, 254, 253, 203, 156, 253, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 93, 253, 254, 121, 13, 93, 253, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 64, 239, 253, 76, 8, 32, 219, 253, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 133, 254, 191, 0, 5, 108, 234, 254, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 132, 253, 190, 5, 85, 253, 236, 154, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 153, 253, 169, 192, 253, 253, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 112, 253, 253, 254, 236, 129, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 17, 118, 243, 191, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
So, the first part of the question is to find the bounding box that contains the image, and the second part is to center the image. For the second part, we'll add debugging to each vertex of the bounding box.
PART 1:
To draw the bounding rectangle, the approach is that we can iterate over each row and find a row with 1 or more non-zero elements, doing this procedure from both top and bottom, we get the limits for Y-axis
and we do the same for X-axis
by iterating over the columns Numpy provides some awesome features like sum()
, we will use this function to check if a row / column has any non-null character, as in this case sum > 0
:
Let (x1, y1) be the top left coordinates and (x2, y2) the bottom right coordinates, these two points are sufficient to define the bounding rectangle.
col_sum = np.where(np.sum(a, axis = 0)>0)
row_sum = np.where(np.sum(a, axis = 1)>0)
y1, y2 = row_sum[0][0], row_sum[0][-1]
x1, x2 = col_sum[0][0], col_sum[0][-1]
print x1, y1
print x2, y2
PART 2:
Now we need to center the image. Instead of calculating the padding required for each side, we simply crop the image into a bounding rectangle and then apply equal padding to each side.
def add_padding(img, pad_l, pad_t, pad_r, pad_b):
height, width = img.shape
#Adding padding to the left side.
pad_left = np.zeros((height, pad_l), dtype = np.int)
img = np.concatenate((pad_left, img), axis = 1)
#Adding padding to the top.
pad_up = np.zeros((pad_t, pad_l + width))
img = np.concatenate((pad_up, img), axis = 0)
#Adding padding to the right.
pad_right = np.zeros((height + pad_t, pad_r))
img = np.concatenate((img, pad_right), axis = 1)
#Adding padding to the bottom
pad_bottom = np.zeros((pad_b, pad_l + width + pad_r))
img = np.concatenate((img, pad_bottom), axis = 0)
return img
cropped_image = img[y1:y2, x1:x2]
padded_image = add_padding(cropped_image, 20, 20, 20, 20)
source to share