opencv图像经过裁剪旋转镜像后的坐标映射

本文详细介绍图像处理中常见的坐标变换算法,包括图像旋转、裁剪、镜像后的坐标计算方法,帮助解决数据增广后标注坐标更新的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们标注完数据之后,因为数据量太小经常会做一些数据增广,但是经过旋转等操作之后,原先标注的坐标肯定会变,这时候计算出经过处理的图像的坐标是很有用的,省的我们拿处理后的图像再去标注.下面将介绍图像旋转,裁剪,镜像之后,对应的图像坐标算法.

# 1.坐标处理函数封装
# 图像镜像后坐标(height,width=原图高度,原图宽度,x,y=原图上某点的坐标(x,y),
# 返回经过纵轴镜像后的坐标(x,y))
def mirror_position(height,width,x,y):
    x_center,y_center = width/2,height/2
    y0 = y
    x0 = 2 * x_center - x
    return round(x0),round(y0)

# 图像裁剪后坐标(height,width=原图高度,原图宽度,x,y=原图上某点的坐标(x,y),
# pro=裁剪比例,返回经过比例裁剪后的坐标(x,y))
def crop_position(height,width,x,y,pro):
    crop_size_x = width/pro
    crop_size_y = height/pro
    x0 = x-crop_size_x
    y0 = y-crop_size_y
    return round(x0),round(y0)

# 图像裁剪后坐标(height,width=原图高度,原图宽度,ori_x,ori_y=原图上某点的坐标(x,y),
# crop_x,crop_y=x轴裁剪大小,y轴裁剪大小,返回经过比例裁剪后的坐标(x,y))
def crop_position_map(ori_x,ori_y,crop_x,crop_y):
    new_x = ori_x - crop_x
    new_y = ori_y - crop_y
    return new_x,new_y

# 图像镜像后坐标(h,w=原图高度,原图宽度,angle旋转角度(注意顺逆时针旋转),
# x1,y1=原图上某点的坐标(x,y),x2,y2=原图中点坐标(x,y),返回经过纵轴镜像后的坐标(x,y))
def rotate_position(w,h,angle,x1,y1,x2,y2):
    y1 = h - y1
    y2 = h - y2
    x = (x1 - x2) * math.cos(math.pi / 180.0 * angle) - (y1 - y2) * math.sin(math.pi / 180.0 * angle) + x2
    y = (x1 - x2) * math.sin(math.pi / 180.0 * angle) + (y1 - y2) * math.cos(math.pi / 180.0 * angle) + y2
    y = h - y
    return round(x),round(y)


# 2. 图像处理
image_path = 'xxx.jpg'
image_np = cv2.imread(image_path)
img_h, img_w = image_np.shape[:2]
# 图像中点坐标
x0,y0 = img_w / 2, img_h / 2
# 旋转一定角度
# angle  = 20
# M = cv2.getRotationMatrix2D((x0,y0), angle, 1.0)
# image_np = cv2.warpAffine(image_np, M, (img_w, img_h))

# 水平镜像
image_np = cv2.flip(image_np, 1, dst=None)

# 裁剪
# proportion = 15   # 裁剪比例
#image_np= image_np[round(img_h/proportion):img_h,round(img_w/proportion):round(img_w-img_w/proportion)]

# 例子:设点(x,y),返回的x1,y1即为新的坐标
x1,y1 = mirror_position(img_h,img_w,x,y)

 

<think>好的,用户的问题是关于图像旋转的编程实现,特别是间接法。我需要先理解间接法和直接法的区别。直接法通常是遍历图像的每个像素,计算旋转后的位置并填充到新图像中,这样可能会导致空洞或重叠。而间接法则是遍历目标图像的每个像素,通过逆变换找到在图像中的对应位置,然后进行插值,这样可以避免空洞的问题。 接下来,用户提供的引用中有一些相关的信息。引用[3]提到旋转使用坐标转换和双线性插值,并且在处理特定角度时使用镜像来提高速度。引用[4]展示了使用OpenCV旋转代码,但那是直接调用库函数,用户需要的是间接法的具体实现,而不是使用现成库。 我需要确定间接法的步骤。首先,计算旋转后的图像尺寸,可能需要调整中心点。然后,对于目标图像的每个像素,应用逆旋转矩阵,找到在图像中的坐标。如果坐标超出图范围,则跳过或处理边界。接着,使用双线性插值来获取像素值,确保图像平滑。 用户可能需要一个不使用OpenCV等库的示例代码,而是手动实现旋转和插值。因此,我需要编写这样的代码,可能使用Python和NumPy来处理数组,Pillow库来读写图像。需要注意旋转矩阵的构造,尤其是逆变换的部分。旋转矩阵的逆矩阵是转置矩阵,因为旋转矩阵是正交矩阵。 在代码中,首先读取图像,获取尺寸。然后计算旋转后的新尺寸,可能需要调整中心位置。创建目标图像数组,遍历每个像素,应用逆变换得到图坐标,使用双线性插值计算像素值。最后保存图像。 另外,需要考虑角度转换为弧度,处理旋转后的边界区域,以及插值时可能出现的越界问题,比如使用np.clip来限制坐标在图像范围内。 需要验证代码的正确性,可能需要测试不同角度,尤其是90度、-90度等特殊角度,看是否正确处理,但根据引用[3],这些角度可能用镜像处理,但用户的问题可能不涉及这些优化,所以暂时先实现通用方法。 最后,生成相关问题,比如间接法的优缺点、插值方法的选择、处理黑边的方法等,帮助用户进一步学习。</think>### 图像旋转间接法编程实现 #### 间接法理 间接法通过遍历目标图像每个像素点,反向映射到图像坐标进行采样,配合插值算法实现平滑旋转。数学公式为: $$x_{src} = (x_{dst}-c_x)\cosθ + (y_{dst}-c_y)\sinθ + c_x$$ $$y_{src} = -(x_{dst}-c_x)\sinθ + (y_{dst}-c_y)\cosθ + c_y$$ 其中$(c_x,c_y)$为旋转中心坐标[^3] #### Python实现代码(基于双线性插值) ```python import numpy as np from PIL import Image def indirect_rotation(img, angle_deg): # 参数处理 angle = np.deg2rad(angle_deg) h, w = img.shape[:2] cx, cy = w//2, h//2 # 旋转中心设为图像中心 # 计算新图像尺寸 new_w = int(w * abs(np.cos(angle)) + h * abs(np.sin(angle))) new_h = int(w * abs(np.sin(angle)) + h * abs(np.cos(angle))) rotated = np.zeros((new_h, new_w, 3), dtype=np.uint8) new_cx, new_cy = new_w//2, new_h//2 # 遍历目标图像每个像素 for y_dst in range(new_h): for x_dst in range(new_w): # 坐标平移后旋转 x_rel = x_dst - new_cx y_rel = y_dst - new_cy x_src = x_rel * np.cos(angle) + y_rel * np.sin(angle) + cx y_src = -x_rel * np.sin(angle) + y_rel * np.cos(angle) + cy # 双线性插值 if 0 <= x_src < w-1 and 0 <= y_src < h-1: x0 = int(x_src) y0 = int(y_src) x1 = x0 + 1 y1 = y0 + 1 # 计算权重 dx = x_src - x0 dy = y_src - y0 # 插值计算 rotated[y_dst, x_dst] = ( (1-dx)*(1-dy)*img[y0, x0] + dx*(1-dy)*img[y0, x1] + (1-dx)*dy*img[y1, x0] + dx*dy*img[y1, x1] ) return rotated # 使用示例 image = Image.open('input.jpg') img_array = np.array(image) rotated_img = indirect_rotation(img_array, 30) # 旋转30度 Image.fromarray(rotated_img).save('output.jpg') ``` #### 关键实现要点 1. **坐标转换**:采用以图像中心为点的相对坐标系,避免边缘裁剪 2. **尺寸计算**:新图像尺寸根据旋转角度动态计算,确保完整包含旋转后的图像 3. **边界处理**:通过`0 <= x_src < w-1`条件过滤超出图范围的像素 4. **插值优化**:使用双线性插值保持图像平滑度 5. **内存优化**:预分配目标图像数组提升处理效率
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值