[英]How to paste a small image on another big image at center in python with an image processed with OpenCV?
I am learning OpenCV and tried to paste a small image over a large image. 我正在学习OpenCV,并尝试在大图像上粘贴小图像。 But, it showed an error as both the images should have an equal size. 但是,由于两个图像的大小均应相等,因此显示错误。 I have also tried to follow the suggestion provided ( How to paste an image onto a larger image using Pillow? ) and ( How do you composite an image onto another image with PIL in Python? ) 我还尝试遵循提供的建议( 如何使用Pillow将图像粘贴到更大的图像上? )和( 如何使用Python中的PIL将图像合成到另一个图像上? )
import cv2 as cv
from scipy import ndimage
img1 = cv.imread('Please put your file name')
top_left_x = min([x1,x2,x3,x4])
top_left_y = min([y1,y2,y3,y4])
bot_right_x = max([x1,x2,x3,x4])
bot_right_y = max([y1,y2,y3,y4])
y_right =bot_right_y + 1
x_right =bot_right_x + 1
cropped = img[top_left_y: y_right, top_left_x: x_right]
rotate = ndimage.rotate(cropped, ang)
The final output image should be at centre. 最终输出图像应居中。
This is a Pure PIL solution:- 这是一个纯PIL解决方案:-
from PIL import Image
img1 = Image.open(r"Source_Image_path")
# The values used to crop the original image (will form a bbox)
x1, y1, x2, y2 = 10, 10, 400, 400
# The angle at which the cropped Image must be rotated
angle = 50
# cropping the original image
img = img1.crop((x1, y1, x2, y2))
# Firstly converting the Image mode to RGBA, and then rotating it
img = img.convert("RGBA").rotate(angle, resample=Image.BICUBIC)
# calibrating the bbox for the beginning and end position of the cropped image in the original image
# i.e the cropped image should lie in the center of the original image
x1 = int(.5 * img1.size[0]) - int(.5 * img.size[0])
y1 = int(.5 * img1.size[1]) - int(.5 * img.size[1])
x2 = int(.5 * img1.size[0]) + int(.5 * img.size[0])
y2 = int(.5 * img1.size[1]) + int(.5 * img.size[1])
# pasting the cropped image over the original image, guided by the transparency mask of cropped image
img1.paste(img, box=(x1, y1, x2, y2), mask=img)
# converting the final image into its original color mode, and then saving it
img1.convert(img1.mode).save("Destination_path")
INPUT IMAGE:- 输入图像:
OUTPUT IMAGE:- 输出图像:
The code itself is self explanatory, but you might be wondering why are we converting the cropped image back and forth to RGBA
. 该代码本身是不言自明的,但是您可能想知道为什么我们将裁剪后的图像来回转换为RGBA
。 The reason for that is, because if we rotate a non alpha image in PIL, we end up with black bars/edges on the image where the pixel values no longer exists ( read this question for more ). 这样做的原因是,因为如果我们在PIL中旋转非alpha图像,则最终在图像上的黑条/边缘将出现像素值不再存在的情况( 有关更多信息,请阅读此问题 )。 But if we do the same for an alpha image, ie passing an alpha image via rotate()
then the empty pixel values end up being fully transparent (or alpha = 0). 但是,如果我们对Alpha图像执行相同操作,即通过rotate()
传递Alpha图像,则空像素值最终将完全透明(或Alpha = 0)。
Although, none of the solution available worked for OpenCV and not even sorted my issue. 虽然,没有可用的解决方案可用于OpenCV,甚至无法解决我的问题。 But, after several modifications, I am able to solve this issue in OpenCV. 但是,经过几次修改,我就能在OpenCV中解决此问题。
import cv2
img = cv2.imread('Please put your file name')
# Setting the parameters
ang = 47
top_left_x = min([12,42,53,11])
top_left_y = min([41,56,75,20])
bot_right_x = max([12,42,53,11])
bot_right_y = max([41,56,75,20])
y_right =bot_right_y + 1
x_right =bot_right_x + 1
# Cropping the image
cropped_img = img[top_left_y: y_right, top_left_x: x_right]
########### Rotating the image ##########
# First setting the centre and roatation angle parameter.
# To rotate sub-image from the centre of the original image
rows,cols = img.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),ang,1)
# Setting the size with original image to resolve size issue
rotated_img = cv2.warpAffine(cropped_img,M,(img.shape[1],img.shape[0]))
# Pasting the rotated image on original image
# The original image will be in the background with transparency 0.3
# The sub-image will be pasted above the original image with transparency 0.7
img = cv2.addWeighted(img, 0.3, rotated_img, 0.7, 0)
# Showing the image
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.imshow('output_image.jpg', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
This would not be the most appropriate answer but can serve the purpose for many of us. 这不是最合适的答案,但可以为我们许多人服务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.