OpenCV透视变换-不对原图裁剪

发布时间 2023-11-09 09:43:42作者: 海_纳百川

前言:

最近在做透视变换,初次尝试是使用Pillow的transform方法,但是该方法在变换以后,由于需要提前设置变换后的图像尺寸,所以导致变换后的图像超出尺寸的部分会发生裁剪问题,这个现象不太适合我的目的,我的目的是对png图进行透视变换,然后贴在一张图上。

 

后来用了opencv中的方法,这个方法不会对图像进行裁剪,但是图像会出现一些多余的透明区域,因此再进行一步根据像素值非0进行裁剪即可

import cv2
import numpy as np

img = cv2.imread('sample.png')

height, width, channel = img.shape

# 判断是不是四通道,如果不是需要转换
if channel != 4:
    # 创建一个具有4通道(RGBA)的目标图像
    rgba_image = np.zeros((height, width, 4), dtype=np.uint8) 
    # 将RGB图像的通道复制到RGBA图像中 
    rgba_image[:, :, :3] = rgb_image 
    # 初始化Alpha通道为不透明(255) 
    rgba_image[:, :, 3] = 255 # 设置Alpha通道 
    img = rgba_image

# 原目标的四个点位置,分别对应,左上角,右上角,左下角,右下角
src = np.float32([[0,0], [width, 0], [0, height], [width, height]])
#变换后的四个顶点位置,设置随机值
left_top_h = random.randint(0, int(0.35*height))
left_top_w = random.randint(0, int(0.35*width))

right_top_h = random.randint(0, int(0.35*height))
right_top_w = random.randint(int(0.65*width), width)

left_button_h = random.randint(int(0.65*height), height)
left_button_w = random.randint(0, int(0.35*width))

right_button_h = random.randint(int(0.65*height), height)
right_button_w = random.randint(int(0.65*width), width)

dst = np.float32([[left_top_w, left_top_h], [right_top_w, right_top_h], [left_button_w, left_button_h], [right_button_w, right_button_h]])

matrix = cv2.getPerspectiveTransform(src, dst)
imgOutput = cv2.warpPerspective(img, matrix, (width, height))

# 对结果进行裁剪
# 查找不透明像素的边界 
non_transparent_pixels = cv2.findNonZero(imgOutput[:, :, 3]) 
x, y, w, h = cv2.boundingRect(non_transparent_pixels) 
# 裁剪图像 
cropped_image = imgOutput[y:y+h, x:x+w]

# 保存结果
cv2.imwrite('transform.png', imgOutput)


# 注意,以上是opencv的方式,如果你使用pil读取图像,返回也需要pil格式,就需要对其进行变换
# 假设pil读取png图像
pil_img = Image.open('sample.png').convert('RGBA')
img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)

# 保存的时候将cv2格式转为pil

imgOutput = cv2.cvtColor(imgOutput, cv2.COLOR_BGRA2RGBA)
imgOutput = Image.fromarray(imgOutput)