Python OpenCV如何提取图像倾斜边生成1像素高RGBA图像
实现方法
核心思路是放弃全图掩码遮罩、外接矩形裁剪的绕路方案,直接沿线段路径逐像素采样,天然适配任意倾斜角度的线段,输出结果直接就是要求的1像素高、长度匹配线段实际像素长度的RGBA数组,没有冗余透明像素。
具体步骤
- 先对单条线段的两个端点做欧氏距离计算,结果向上取整就是输出图像的宽度,对应最终输出的
(1, N, 4)维度里的N值 - 用线性插值生成线段路径上所有N个像素的坐标,不需要额外做图像旋转、透视变换,避免插值带来的像素失真
坐标插值用浮点计算,转整数索引时加一层边界判断,避免坐标超出原图宽高范围触发索引报错
- 提前把输入图像转成4通道RGBA格式,3通道BGR图可以直接用
cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)补全alpha通道 - 按顺序遍历插值得到的所有线段坐标,直接从原图数组中取对应位置的RGBA像素值,超出图像范围的点直接补
[0,0,0,0]透明值 - 把采集到的N个像素值转成numpy数组,reshape成
(1, N, 4)的形状即可,不需要额外做裁剪、去透明边操作
可直接运行的代码
import cv2 import numpy as np def extract_single_edge(img_rgba, point_a, point_b): """ 提取单条边对应的1像素高RGBA图像片段 参数: img_rgba: 4通道RGBA格式的原图数组 point_a, point_b: 线段两个端点,格式为(x, y),坐标顺序不影响输出 返回: 形状为(1, 线段像素长度, 4)的uint8格式数组 """ x1, y1 = point_a x2, y2 = point_b # 计算线段实际像素长度,确定采样点总数 seg_length = int(np.ceil(np.hypot(x2 - x1, y2 - y1))) # 线性插值生成线段上所有采样点的坐标 x_samples = np.linspace(x1, x2, seg_length) y_samples = np.linspace(y1, y2, seg_length) img_h, img_w = img_rgba.shape[:2] pixel_list = [] for x, y in zip(x_samples, y_samples): x_idx = int(round(x)) y_idx = int(round(y)) # 边界保护:超出图像范围的位置补透明像素 if 0 <= x_idx < img_w and 0 <= y_idx < img_h: pixel_list.append(img_rgba[y_idx, x_idx]) else: pixel_list.append([0, 0, 0, 0]) return np.array(pixel_list, dtype=np.uint8).reshape(1, seg_length, 4) # 批量处理示例 if __name__ == "__main__": # 读入图像,统一转RGBA格式 origin_img = cv2.imread("your_target_image.png", cv2.IMREAD_UNCHANGED) if origin_img.shape[2] == 3: img_rgba = cv2.cvtColor(origin_img, cv2.COLOR_BGR2RGBA) else: img_rgba = origin_img # 题目给出的6条边顶点集 edge_vertices = [ [[107, 32], [95, 30]], [[95, 30], [26, 103]], [[26, 103], [28, 119]], [[28, 119], [103, 109]], [[103, 109], [122, 64]], [[122, 64], [107, 32]] ] all_edge_segments = [] for idx, (p1, p2) in enumerate(edge_vertices): seg = extract_single_edge(img_rgba, p1, p2) all_edge_segments.append(seg) # 如需保存单条边结果,取消下一行注释即可 # cv2.imwrite(f"edge_segment_{idx+1}.png", cv2.cvtColor(seg, cv2.COLOR_RGBA2BGRA))
原有方案的问题说明
- 全图绘制掩码再做遮罩的方案,输出始终和原图尺寸一致,即使后续裁剪非透明区域的最小外接矩形,倾斜线段对应的外接矩形仍然是倾斜的矩形区域,会包含大量非线段的透明/非透明像素,无法得到1像素高度的结果
- 直接数组切片仅能适配完全水平、垂直的轴对齐线段,倾斜线段的像素坐标不满足行/列索引连续的要求,要么漏取像素要么取到线段外的冗余内容
内容的提问来源于stack exchange,提问作者Mario Turco
相关产品推荐
相关产品推荐

