opencv在图像上绘制直线或指定区域

1. opencv在图像中绘制直线

  • opencv可以利用selectROI在图像上选择矩形框,并返回相应的的坐标,其源码在https://github.com/opencv/opencv/blob/17234f82d025e3bbfbf611089637e5aa2038e7b8/modules/highgui/src/roiSelector.cpp

  • 这里我们依葫芦画瓢,搞个在图像中实时绘制直线的版本

import cv2
class LineSelector:
    """
    在图像上实时绘制线段(类似selectROIs),并返回起始和终点坐标
    """
    def __init__(self):
        self.lines = []
        self.image = None
        self.start_pos = None
        self.end_pos = None
        self.is_drawing = None

    def draw_lines(self, img_bgr, window_name='roi'):
        cv2.imshow(window_name, img_bgr)
        self.image = img_bgr.copy()
        cv2.setMouseCallback(window_name, self.mouse_handler)
        while cv2.waitKey(50) & 0xFF != ord('q'):
            if self.start_pos is not None and self.end_pos is not None:
                x, y = self.start_pos
                cv2.putText(self.image, f'{
      
      x},{
      
      y}', (x, y), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 255))
                # cv2.line(self.image, self.start_pos, self.end_pos, (0, 0, 255))
                cv2.arrowedLine(self.image, self.start_pos, self.end_pos, (0, 0, 255))
                x, y = self.end_pos
                cv2.putText(self.image, f'{
      
      x},{
      
      y}', (x, y), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 255))
                cv2.imshow(window_name, self.image)
            self.image = img_bgr.copy()
            cv2.waitKey(30)
        cv2.setMouseCallback(window_name, self.empty_handler)
        cv2.destroyWindow(window_name)
        return self.lines

    def empty_handler(self, event, x, y, flags, params):
        pass

    def mouse_handler(self, event, x, y, flags, params):
        self.mouse_callback(event, x, y, flags, params)

    def mouse_callback(self, event, x, y, flags, params):
        if event == cv2.EVENT_MOUSEMOVE:
            if self.is_drawing:
                self.end_pos = (x, y)
        if event == cv2.EVENT_LBUTTONDOWN:
            self.is_drawing = True
            self.start_pos = (x, y)
        if event == cv2.EVENT_LBUTTONUP:
            self.is_drawing = False
            if self.start_pos is not None and self.end_pos is not None:
                self.lines.append([self.start_pos, self.end_pos])
            self.start_pos = None
            self.end_pos = None
  • 用代码测试一下:
img = cv2.imread('data/1.png')
ls = LineSelector()
lines = ls.draw_lines(img)
print(lines)  # 返回起始坐标和终点坐标 [[(202, 502), (441, 288)]]

(注:画完按 q 结束)

  • 效果如下:
    在这里插入图片描述

2. opencv在图像中选择指定区域

  • 结合第一步绘制的直线,以及cv2.fillPoly,将绘制直线坐标首尾相连起来,并在指定区域内填充值
  • 直接上代码
import cv2
import numpy as np
from draw_api import LineSelector

ls = LineSelector()


def draw_region(img_bgr):
    h, w, _ = img_bgr.shape
    region = np.zeros((h, w))

    lines = ls.draw_lines(img_bgr)
    area = np.array([p for line in lines for p in line])
    img_region = cv2.fillPoly(region, [area], (1, 0, 0))
    return img_region


if __name__ == '__main__':
    img = cv2.imread('data/1.png')
    img_region = draw_region(img)
    cv2.imshow('windows', img_region)
    cv2.waitKey(0)
  • 这里我们画两条线,
    在这里插入图片描述

  • 运行程序,查看效果:
    在这里插入图片描述

结束。

猜你喜欢

转载自blog.csdn.net/weixin_43508499/article/details/123175809