如何旋转图像以获得非空像素?
How to rotate an image to get not-null pixels?
在我下面链接的图像中,我需要获取此旋转矩形中的所有 yellow/green 像素并去除蓝色背景,以便矩形的轴与 x 轴和 y 轴对齐。
我正在使用 numpy,但不知道我应该做什么。
我在此 drive 中上传了数组,以防有人想要使用实际数组
提前感谢您的帮助。
我知道 numpys 加载方法中有一个 allow_pickle=False
选项,但我对来自互联网的 unpickling/using 数据感到不舒服,所以我使用了小图像。删除坐标系和我拥有的东西后
我定义了两个辅助方法。一个用于稍后旋转从另一个堆栈溢出线程获取的图像。请参阅下面的 link。一个是让掩码在指定颜色处为 1,否则为 0。
import numpy as np
import matplotlib.pyplot as plt
import sympy
import cv2
import functools
color = arr[150,50]
def similar_to_boundary_color(arr, color=tuple(color)):
mask = functools.reduce(np.logical_and, [np.isclose(arr[:,:,i], color[i]) for i in range(4)])
return mask
#
def rotate_image(image, angle):
image_center = tuple(np.array(image.shape[1::-1]) / 2)
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
return result
接下来我计算要旋转的角度。我通过找到宽度为 50 和 300 的最低像素来做到这一点。我选择了那些,因为它们离边界足够远,不会受到缺失角等的影响。
i,j = np.where(~similar_to_boundary_color(arr))
slope = (max(i[j == 50])-max(i[j == 300]))/(50-300)
angle = np.arctan(slope)
arr = rotate_image(arr, np.rad2deg(angle))
plt.imshow(arr)
.
进行裁剪的一种方法如下。您计算高度和宽度的中间值。然后你在中间取两个切片,比如在一个方向上 20 个像素,直到另一个方向的中间。像素为 white/background 颜色的 biggest/smallest 索引是一个合理的剪切点。
i,j = np.where(~(~similar_to_boundary_color(arr) & ~similar_to_boundary_color(arr, (0,0,0,0))))
imid, jmid = np.array(arr.shape)[:2]/2
imin = max(i[(i < imid) & (jmid - 10 < j) & (j < jmid + 10)])
imax = min(i[(i > imid) & (jmid - 10 < j) & (j < jmid + 10)])
jmax = min(j[(j > jmid) & (imid - 10 < i) & (i < imid + 10)])
jmin = max(j[(j < jmid) & (imid - 10 < i) & (i < imid + 10)])
arr = arr[imin:imax,jmin:jmax]
plt.imshow(arr)
结果是:
我使用了与 user2640045 相同的图像,但方法不同。
import numpy as np
import cv2
# load and convert image to grayscale
img = cv2.imread('image.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# binarize image
threshold, binarized_img = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# find the largest contour
contours, hierarchy = cv2.findContours(binarized_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
c = max(contours, key = cv2.contourArea)
# get size of the rotated rectangle
center, size, angle = cv2.minAreaRect(c)
# get size of the image
h, w, *_ = img.shape
# create a rotation matrix and rotate the image
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated_img = cv2.warpAffine(img, M, (w, h))
# crop the image
pad_x = int((w - size[0]) / 2)
pad_y = int((h - size[1]) / 2)
cropped_img = rotated_img[pad_y : pad_y + int(size[1]), pad_x : pad_x + int(size[0]), :]
结果:
在我下面链接的图像中,我需要获取此旋转矩形中的所有 yellow/green 像素并去除蓝色背景,以便矩形的轴与 x 轴和 y 轴对齐。
我正在使用 numpy,但不知道我应该做什么。
我在此 drive 中上传了数组,以防有人想要使用实际数组
提前感谢您的帮助。
我知道 numpys 加载方法中有一个 allow_pickle=False
选项,但我对来自互联网的 unpickling/using 数据感到不舒服,所以我使用了小图像。删除坐标系和我拥有的东西后
我定义了两个辅助方法。一个用于稍后旋转从另一个堆栈溢出线程获取的图像。请参阅下面的 link。一个是让掩码在指定颜色处为 1,否则为 0。
import numpy as np
import matplotlib.pyplot as plt
import sympy
import cv2
import functools
color = arr[150,50]
def similar_to_boundary_color(arr, color=tuple(color)):
mask = functools.reduce(np.logical_and, [np.isclose(arr[:,:,i], color[i]) for i in range(4)])
return mask
#
def rotate_image(image, angle):
image_center = tuple(np.array(image.shape[1::-1]) / 2)
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
return result
接下来我计算要旋转的角度。我通过找到宽度为 50 和 300 的最低像素来做到这一点。我选择了那些,因为它们离边界足够远,不会受到缺失角等的影响。
i,j = np.where(~similar_to_boundary_color(arr))
slope = (max(i[j == 50])-max(i[j == 300]))/(50-300)
angle = np.arctan(slope)
arr = rotate_image(arr, np.rad2deg(angle))
plt.imshow(arr)
进行裁剪的一种方法如下。您计算高度和宽度的中间值。然后你在中间取两个切片,比如在一个方向上 20 个像素,直到另一个方向的中间。像素为 white/background 颜色的 biggest/smallest 索引是一个合理的剪切点。
i,j = np.where(~(~similar_to_boundary_color(arr) & ~similar_to_boundary_color(arr, (0,0,0,0))))
imid, jmid = np.array(arr.shape)[:2]/2
imin = max(i[(i < imid) & (jmid - 10 < j) & (j < jmid + 10)])
imax = min(i[(i > imid) & (jmid - 10 < j) & (j < jmid + 10)])
jmax = min(j[(j > jmid) & (imid - 10 < i) & (i < imid + 10)])
jmin = max(j[(j < jmid) & (imid - 10 < i) & (i < imid + 10)])
arr = arr[imin:imax,jmin:jmax]
plt.imshow(arr)
结果是:
我使用了与 user2640045 相同的图像,但方法不同。
import numpy as np
import cv2
# load and convert image to grayscale
img = cv2.imread('image.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# binarize image
threshold, binarized_img = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# find the largest contour
contours, hierarchy = cv2.findContours(binarized_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
c = max(contours, key = cv2.contourArea)
# get size of the rotated rectangle
center, size, angle = cv2.minAreaRect(c)
# get size of the image
h, w, *_ = img.shape
# create a rotation matrix and rotate the image
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated_img = cv2.warpAffine(img, M, (w, h))
# crop the image
pad_x = int((w - size[0]) / 2)
pad_y = int((h - size[1]) / 2)
cropped_img = rotated_img[pad_y : pad_y + int(size[1]), pad_x : pad_x + int(size[0]), :]
结果: