python3实现cv2+numpy裁剪不规则四边形图片

该文章介绍了一种使用Python3、cv2和numpy库来实现从图片中裁剪不规则四边形的方法,保持图片不变形且不旋转。核心代码涉及创建掩模、填充多边形以及位运算来提取目标区域。

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

功能

从给定的图片中裁剪不规则四边形,保持图片不变形,不旋转。

效果图在这里插入图片描述

依赖环境

  • cv2
  • numpy
  • python3

核心代码

    mask = np.zeros(img.shape, dtype=np.uint8)
    roi_corners = np.array([quad], dtype=np.int32)
    
    ignore_mask_color = (255,) * img.shape[2]
    cv2.fillPoly(mask, roi_corners, ignore_mask_color)
    
    masked_img = cv2.bitwise_and(img, mask)

szZack的博客

测试结果

  • 输入图片
    在这里插入图片描述

  • 输出图片
    在这里插入图片描述

  • 完整效果图
    在这里插入图片描述

完整代码

szZack的博客

import cv2
import numpy as np
import argparse

# 从图片中截取不规则四边形图片
def crop_quadrilateral(img, quad):
    # img: cv2彩色图片
    # quad: [(1,1), (3,3), (2,6), (5,8)]
    
    mask = np.zeros(img.shape, dtype=np.uint8)
    roi_corners = np.array([quad], dtype=np.int32)
    
    ignore_mask_color = (255,) * img.shape[2]
    cv2.fillPoly(mask, roi_corners, ignore_mask_color)
    
    masked_img = cv2.bitwise_and(img, mask)
    masked_img[np.where(masked_img==0)] = 255
    
    return masked_img
    
    
if __name__ == '__main__':
    # python crop_quadrilateral.py --image_path=123.jpg --left_up_x=111 --left_up_y=15 --right_up_x=532 --right_up_y=62 --right_down_x=529 --right_down_y=93  --left_down_x=108 --left_down_y=46
    parser = argparse.ArgumentParser(description="crop_quadrilateral")
    
    parser.add_argument('--image_path', help='image path', type=str)
    parser.add_argument('--left_up_x', help='left_up_point', type=int)
    parser.add_argument('--left_up_y', help='left_up_point', type=int)
    parser.add_argument('--left_down_x', help='left_down_point', type=int)
    parser.add_argument('--left_down_y', help='left_down_point', type=int)
    parser.add_argument('--right_up_x', help='right_up_point', type=int)
    parser.add_argument('--right_up_y', help='right_up_point', type=int)
    parser.add_argument('--right_down_x', help='right_down_point', type=int)
    parser.add_argument('--right_down_y', help='right_down_point', type=int)
    
    args = parser.parse_args()
    
    img = cv2.imread(args.image_path)
    quad = [(args.left_up_x, args.left_up_y), (args.right_up_x, args.right_up_y), \
            (args.right_down_x, args.right_down_y), (args.left_down_x, args.left_down_y)]
    crop_img = crop_quadrilateral(img, quad)
    cv2.imwrite('./crop_img.jpg', crop_img)
### 使用Python从非矩形或自定义形状区域内提取图像像素 为了实现从非矩形或自定义形状区域内提取图像像素,在Python中有多种方法可以完成此任务。常用的技术涉及创建掩模(mask),该掩模定义哪些像素属于感兴趣的区域,随后利用这个掩模来筛选原始图像中的相应像素。 #### 方法一:使用PIL库与NumPy结合 当目标是从特定形状内获取像素时,可以通过`Pillow`库绘制所需的形状作为掩模,并借助于`NumPy`数组操作来进行高效的像素选取。下面是一个简单的例子展示如何做到这一点: ```python from PIL import Image, ImageDraw import numpy as np # 创建一个新的白色背景图片 img = Image.new('RGB', (500, 500), color = 'white') draw = ImageDraw.Draw(img) # 定义一个多边形轮廓点列表 polygon_points = [(100, 150), (300, 200), (400, 350), (250, 400)] # 在新图层上画出多边形并填充黑色表示选区 mask_img = Image.new('L', img.size, 0) ImageDraw.Draw(mask_img).polygon(polygon_points, fill=255) # 将原图转换成numpy array形式以便后续处理 np_img = np.array(img) # 应用掩码到原图数据上得到裁剪后的结果 masked_np_img = cv2.bitwise_and(np_img, np_img, mask=np.array(mask_img)) # 转回image对象显示最终效果 result_image = Image.fromarray(masked_np_img) result_image.show() ``` 这段代码先建立了一个新的空白图像文件,接着在其副本上描绘出了想要的任意形状——这里是以四个顶点构成的一个四边形为例;之后再把这个图形转为二值化的灰度模式(`'L'`)下的遮罩图像,其中被标记出来的部分即为我们所关心的对象所在位置。最后一步则是运用布尔逻辑运算符将这些信息施加给源图像的数据集,从而实现了只保留选定范围内的色彩信息的效果[^1]。 #### 方法二:基于OpenCV的手动选择ROI 另一种方式是采用交互式的手段让用户自己去圈定感兴趣的部分,这主要依赖于`cv2.setMouseCallback()`函数监听鼠标的点击事件,进而动态调整覆盖在视频帧上的透明蒙版大小直至满意为止。这种方式非常适合那些难以提前预知确切几何特征的情况。 ```python import cv2 def draw_circle(event,x,y,flags,param): global ix,iy,drawing,mode if event == cv2.EVENT_LBUTTONDOWN: drawing = True ix,iy = x,y elif event == cv2.EVENT_MOUSEMOVE: if drawing == True: if mode == True: cv2.circle(img,(x,y),5,(0,0,255),-1) elif event == cv2.EVENT_LBUTTONUP: drawing = False if mode == True: cv2.circle(img,(x,y),5,(0,0,255),-1) drawing = False # true if mouse is pressed ix,iy = -1,-1 img = np.zeros((512,512,3), np.uint8) cv2.namedWindow('image') cv2.setMouseCallback('image',draw_circle) while(1): cv2.imshow('image',img) k = cv2.waitKey(1) & 0xFF if k == ord('m'): mode = not mode elif k == 27: break cv2.destroyAllWindows() # 提取由用户绘制的所有红色圆形组成的区域作为ROI gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY) contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2:] roi_mask = np.zeros_like(gray) cv2.drawContours(roi_mask, contours, -1, 255, thickness=cv2.FILLED) # 对实际输入图像应用上述获得的ROI Mask... input_image = ... # 加载待处理的真实图像路径 output = cv2.bitwise_and(input_image,input_image,mask = roi_mask) ``` 在这个脚本里,通过设置回调机制允许使用者自由地在窗口内部勾勒闭合曲线,每当松开按钮后就会自动形成封闭的空间供下一步骤调用。一旦完成了整个过程,则可依据之前累积下来的轨迹构建起完整的边界描述并向外扩展至完全包围住所有已标注过的斑点群组,以此为基础建立起精确匹配的选择条件[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

szZack

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值