OpenCV透视变换-不对原图裁剪
前言:
最近在做透视变换,初次尝试是使用Pillow的transform方法,但是该方法在变换以后,由于需要提前设置变换后的图像尺寸,所以导致变换后的图像超出尺寸的部分会发生裁剪问题,这个现象不太适合我的目的,我的目的是对png图进行透视变换,然后贴在一张图上。以下是pil的方式
from PIL import Image import numpy def find_coeffs(pa, pb): matrix = [] for p1, p2 in zip(pa, pb): matrix.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]]) matrix.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]]) A = numpy.matrix(matrix, dtype=numpy.float) B = numpy.array(pb).reshape(8) res = numpy.dot(numpy.linalg.inv(A.T * A) * A.T, B) return numpy.array(res).reshape(8) # test.png is a 256x256 white square img = Image.open("./images/test.png") # 根据原始点和目标点,求得变换矩阵 coeffs = find_coeffs( [(0, 0), (256, 0), (256, 256), (0, 256)], [(15, 115), (140, 20), (140, 340), (15, 250)]) img.transform((300, 400), Image.PERSPECTIVE, coeffs,Image.BICUBIC).show()
后来用了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)
本文来自博客园,作者:海_纳百川,转载请注明原文链接:https://www.cnblogs.com/chentiao/p/17818051.html,如有侵权联系删除
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
2022-11-08 IOU计算-纯python
2022-11-08 awk强势使用方法