返回顶部
首页 > 资讯 > 精选 >基于OpenCV如何实现动态画矩形和多边形并保存坐标
  • 498
分享到

基于OpenCV如何实现动态画矩形和多边形并保存坐标

2023-07-05 15:07:23 498人浏览 独家记忆
摘要

这篇文章主要讲解了“基于OpenCV如何实现动态画矩形和多边形并保存坐标”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于OpenCV如何实现动态画矩形和多边形并保存坐标”吧!1 画矩形和多

这篇文章主要讲解了“基于OpenCV如何实现动态画矩形和多边形并保存坐标”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于OpenCV如何实现动态画矩形和多边形并保存坐标”吧!

1 画矩形和多边形,模式通过键盘控制

# 通过键盘s和p区别画矩形和多边形并保存坐标# 画矩形是OPencv自带的,只能通过按enter结束 import copyimport JSONimport joblibimport cv2import numpy as npimport osimport matplotlib.pyplot as pltimport imutilsfrom win32 import win32gui, win32printfrom win32.lib import win32conWIN_NAME = 'draw_rect'   def get_list0(path):    if not os.path.exists(path):        print("记录该型号标准位置的文件缺失/或输入型号与其对应标准文件名称不一致")    file1 = open(path, 'r')    lines = file1.readlines()    # for line in lines:    #     if (any(kw in line for kw in kws)):    #         SeriousFix.write(line + '\n')    zb0, list0 = [], []    for i in range(len(lines)):  # 取坐标        if lines[i] != '(pt1,pt2):\n':            zb0.append(lines[i][:-1])    # print(zb0)    for i in range(0, len(zb0)):  # 转换整数        zb0[i] = int(zb0[i])    # print(zb0)     for i in range(0, len(zb0), 4):  # 每四个取一次,加入列表        x0, y0, x1, y1 = zb0[i: i + 4]         # 使点设为左上至右下        if y1<=y0:            temp = y0            y0 = y1            y1 = temp         # print(x0,y0,x1,y1)        list0.append([x0, y0, x1, y1])    print("list0:", list0)    file1.close()    return list0  '''        初始校验文件,文件名代表类型,检验时读取文件名作为类型判断标准        打开sourse文件夹,读取标准件原始图片,保存标准位置到biaozhun/labels,保存画有标准位置的图片到biaozhun/imgs'''def define_start(img_name, img_path, type):    pts = []  # 用于存放点     def draw_roi(event, x, y, flags, param):        img2 = img.copy()        # print("----------")        # cv2.imshow("img2", img2)        # cv2.waiTKEy(0)         if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击,选择点            pts.append((x, y))         if event == cv2.EVENT_RBUTTONDOWN:  # 右键点击,取消最近一次选择的点            pts.pop()         if event == cv2.EVENT_MBUTTONDOWN:  # 中键绘制轮廓             cv2.line(img=img2, pt1=pts[0], pt2=pts[-1], color=(255, 0, 0), thickness=2)             for i in range(len(pts)):                txt_save.append("(pt1,pt2):")                txt_save.append(str(pts[i][0]))                txt_save.append(str(pts[i][1]))         if len(pts) > 0:            # 将pts中的最后一点画出来            cv2.circle(img2, pts[-1], 3, (0, 0, 255), -1)         if len(pts) > 1:            # 画线            for i in range(len(pts) - 1):                cv2.circle(img2, pts[i], 5, (0, 0, 255), -1)  # x ,y 为鼠标点击地方的坐标                cv2.line(img=img2, pt1=pts[i], pt2=pts[i + 1], color=(255, 0, 0), thickness=2)            cv2.line(img=img2, pt1=pts[0], pt2=pts[-1], color=(255, 0, 0), thickness=2)         cv2.imshow(WIN_NAME, img2)     def set_ratio(image):        if image is None:            return 0, 0, 0        # print(image.shape)        img_h, img_w = image.shape[:2]        """获取真实的分辨率"""        hDC = win32gui.GetDC(0)        screen_w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)  # 横向分辨率        screen_h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)  # 纵向分辨率        # print(img_w,img_h)         num_wh = 1        if img_w * img_h > 1.9e7:  # 两千万像素            num_wh = 4        elif img_w * img_h > 1.0e7:  # 一千万像素            num_wh = 3        elif min(img_w, img_h) >= min(screen_w, screen_h) or \                max(img_w, img_h) >= max(screen_w, screen_h):            num_wh = 2        else:            num_wh = 1         ratio_h = int(img_h / num_wh)        ratio_w = int(img_w / num_wh)         return ratio_h, ratio_w, num_wh     (filepath, file) = os.path.split(img_path)     # file = 'r.jpg'      # 需要用户选择图片,传入图片的名称     if file.endswith(".jpg") or file.endswith(".png"):  # 如果file以jpg结尾        # img_dir = os.path.join(file_dir, file)        image = cv2.imread(img_path)         ratio_h, ratio_w, num_wh = set_ratio(image)        if ratio_h == 0 and ratio_w == 0 and num_wh == 0:            print("No image")         txt_path = "./DrawRect/biaozhun/labels/%s.txt" % (img_name)        open(txt_path, 'w').close()  # 清空文件数据        f = open(txt_path, mode='a+')        txt_save = []         img = imutils.resize(image, width = ratio_w)        cv2.namedWindow(WIN_NAME, cv2.WINDOW_NORMAL)        # # cv2.namedWindow(WIN_NAME, 2)        cv2.resizeWindow(WIN_NAME, ratio_w, ratio_h)        cv2.imshow(WIN_NAME, img)        # cv2.waitKey(1)         key = cv2.waitKey(0)         # 矩形        if key == ord("s"):            roi = cv2.selectROI(windowName=WIN_NAME, img=img, showCrosshair=False, fromCenter=False)            x, y, w, h = roi            cv2.rectangle(img=img, pt1=(x, y), pt2=(x + w, y + h), color=(0, 0, 255), thickness=2)             print('pt1: x = %d, y = %d' % (x, y))            txt_save.append("(pt1,pt2):")            txt_save.append(str(x))            txt_save.append(str(y))            txt_save.append(str(x + w))            txt_save.append(str(y + h))             cv2.imshow(WIN_NAME, img)            cv2.waitKey(0)             # 保存txt坐标            num_txt_i = 0            for txt_i in range(len(txt_save)):                txt_i = txt_i - num_txt_i                if txt_save[txt_i] == 'delete':                    for j in range(6):                        del txt_save[txt_i - j]                    num_txt_i += 6            for txt_i in txt_save:                f.write(str(txt_i) + '\n')            print("txt_save:", txt_save)            # break            f.close()             # 查找距离较近的,删除            points_list = get_list0(txt_path)            new_points_list = []            for i in points_list:                x0, y0, x1, y1 = i[0], i[1], i[2], i[3]                if abs(x1 - x0) > 5 and abs(y1 - y0) > 5:                    new_points_list.append('(pt1,pt2):')                    new_points_list.append(x0)                    new_points_list.append(y0)                    new_points_list.append(x1)                    new_points_list.append(y1)            print(new_points_list)            file2 = open(txt_path, 'w')            for i in new_points_list:                file2.write(str(i) + '\n')            file2.close()         # 多边形        elif key == ord("p"):            print("---")             cv2.setMouseCallback(WIN_NAME, draw_roi)             while True:                key = cv2.waitKey(1)                if key == 13 or cv2.getWindowProperty(WIN_NAME, 0) == -1:  # enter回车键:                    # 保存txt坐标                     for i in range(len(pts)):                        txt_save.append("(pt1,pt2):")                        txt_save.append(str(pts[i][0]))                        txt_save.append(str(pts[i][1]))                     num_txt_i = 0                    for txt_i in range(len(txt_save)):                        txt_i = txt_i - num_txt_i                        if txt_save[txt_i] == 'delete':                            for j in range(6):                                del txt_save[txt_i - j]                            num_txt_i += 6                    for txt_i in txt_save:                        f.write(str(txt_i) + '\n')                    print("txt_save:", txt_save)                    # break                    f.close()                 # 现在是多边形之前的方法不行                    # # 查找距离较近的,删除                    # points_list = get_list0(txt_path)                    # new_points_list = []                    # for i in points_list:                    #     x0, y0, x1, y1 = i[0], i[1], i[2], i[3]                    #     if abs(x1 - x0) > 5 and abs(y1 - y0) > 5:                    #         new_points_list.append('(pt1,pt2):')                    #         new_points_list.append(x0)                    #         new_points_list.append(y0)                    #         new_points_list.append(x1)                    #         new_points_list.append(y1)                    # print(new_points_list)                    # file2 = open(txt_path, 'w')                    # for i in new_points_list:                    #     file2.write(str(i) + '\n')                    # file2.close()                     break            cv2.destroyAllwindows()      else:        print("输入图片类型错误!请输入JPG/PNG格式的图片!")   if __name__ == '__main__':    # path_file = open('./datasets/drawPath.json', 'r')    path_file = open('./DataSet/drawPath.json', 'r')    path_dic = json.load(path_file)    img_path = path_dic['path']         # # 绘制标准图片的地址    path_file.close()    img_name = img_path.split('\\')[-1][:-4]    define_start(img_name, img_path, 0)

drawPath.json文件

{"path": "D:\\ALLBuffers\\PyCharm\\OpencvRun\\DataSet\\smpj.jpg"}

2 修改后默认情况下直接画多边形,按鼠标中键切换为画矩形模式

## 1 程序默认运行是直接绘多边形,直接点击即可,## 绘制完成后点击右上角的X或按enter即可关闭图像并保存坐标## 2 在默认情况下,单击鼠标中键或空格即可切换为矩形模式## 3 在绘制矩形模式下只能通过按enter关闭图像并保存坐标## 4 在绘制矩形模式下鼠标左键取消上一步操作或重新绘制矩形## 5 在绘制多边形时鼠标右键取消上一步操作 import copyimport jsonimport joblibimport cv2import numpy as npimport osimport matplotlib.pyplot as pltimport imutilsfrom win32 import win32gui, win32printfrom win32.lib import win32con WIN_NAME = 'draw_rect'  def get_list0(path):    if not os.path.exists(path):        print("记录该型号标准位置的文件缺失/或输入型号与其对应标准文件名称不一致")    file1 = open(path, 'r')    lines = file1.readlines()    # for line in lines:    #     if (any(kw in line for kw in kws)):    #         SeriousFix.write(line + '\n')    zb0, list0 = [], []    for i in range(len(lines)):  # 取坐标        if lines[i] != '(pt1,pt2):\n':            zb0.append(lines[i][:-1])    # print(zb0)    for i in range(0, len(zb0)):  # 转换整数        zb0[i] = int(zb0[i])    # print(zb0)     for i in range(0, len(zb0), 4):  # 每四个取一次,加入列表        x0, y0, x1, y1 = zb0[i: i + 4]         # 使点设为左上至右下        if y1<=y0:            temp = y0            y0 = y1            y1 = temp         # print(x0,y0,x1,y1)        list0.append([x0, y0, x1, y1])    print("list0:", list0)    file1.close()    return list0  '''        初始校验文件,文件名代表类型,检验时读取文件名作为类型判断标准        打开sourse文件夹,读取标准件原始图片,保存标准位置到biaozhun/labels,保存画有标准位置的图片到biaozhun/imgs'''POLYLINES = False  # 多边形向矩形切换  def define_start(img_name, img_path, type):    pts = []  # 用于存放点     def draw_roi(event, x, y, flags, param):         img2 = img.copy()         if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击,选择点            pts.append((x, y))            cv2.circle(img2, pts[-1], 3, (0, 255, 0), -1)        #        # if event == cv2.EVENT_MOUSEMOVE:  # 画圆        #     if len(pts) >= 1:        #         radius = np.sqrt(pow(x-pts[0][0],2) + pow(y-pts[0][1],2))        #         radius = int(radius)        #         rs.append(radius)        #         cv2.circle(img2, pts[0], rs[-1], (0, 0, 255), 2)  # x ,y 为鼠标点击地方的坐标        #          if event == cv2.EVENT_RBUTTONDOWN:  # 右键点击,取消最近一次选择的点            if len(pts) >= 1:                pts.pop()          if event == cv2.EVENT_MBUTTONDOWN:  # 中键绘制轮廓            global POLYLINES            # print("MBUTTONDOWN:  # 中键绘制轮廓")            POLYLINES = True         if len(pts) > 0:            # 将pts中的最后一点画出来            cv2.circle(img2, pts[-1], 3, (0, 255, 0), -1)          if len(pts) > 1:             # 画线            for i in range(len(pts) - 1):                cv2.circle(img2, pts[i], 5, (0, 255, 0), -1)  # x ,y 为鼠标点击地方的坐标                cv2.line(img=img2, pt1=pts[i], pt2=pts[i + 1], color=(0, 0, 255), thickness=2)            cv2.line(img=img2, pt1=pts[0], pt2=pts[-1], color=(0, 0, 255), thickness=2)         cv2.imshow(WIN_NAME, img2)     def set_ratio(image):        if image is None:            return 0, 0, 0        # print(image.shape)        img_h, img_w = image.shape[:2]        """获取真实的分辨率"""        hDC = win32gui.GetDC(0)        screen_w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)  # 横向分辨率        screen_h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)  # 纵向分辨率        # print(img_w,img_h)         num_wh = 1        if img_w * img_h > 1.9e7:  # 两千万像素            num_wh = 4        elif img_w * img_h > 1.0e7:  # 一千万像素            num_wh = 3        elif min(img_w, img_h) >= min(screen_w, screen_h) or \                max(img_w, img_h) >= max(screen_w, screen_h):            num_wh = 2        else:            num_wh = 1         ratio_h = int(img_h / num_wh)        ratio_w = int(img_w / num_wh)         return ratio_h, ratio_w, num_wh     (filepath, file) = os.path.split(img_path)     # file = 'r.jpg'      # 需要用户选择图片,传入图片的名称     if file.endswith(".jpg") or file.endswith(".png"):  # 如果file以jpg结尾        # img_dir = os.path.join(file_dir, file)        image = cv2.imread(img_path)         ratio_h, ratio_w, num_wh = set_ratio(image)        if ratio_h == 0 and ratio_w == 0 and num_wh == 0:            print("No image")         txt_path = "./DrawRect/biaozhun/labels/%s.txt" % (img_name)        open(txt_path, 'w').close()  # 清空文件数据        f = open(txt_path, mode='a+')        txt_save = []         img = imutils.resize(image, width = ratio_w)        cv2.namedWindow(WIN_NAME, cv2.WINDOW_NORMAL)        cv2.resizeWindow(WIN_NAME, ratio_w, ratio_h)        cv2.imshow(WIN_NAME, img)         # 默认直接执行画多边形        cv2.setMouseCallback(WIN_NAME, draw_roi)         while True:            w_key = cv2.waitKey(1)            # enter 或回车键:            if w_key == 13 or cv2.getWindowProperty(WIN_NAME, 0) == -1:                for i in range(len(pts)):                    if i == 0:                      txt_save.append("(pt1,pt2):")                    txt_save.append(str(pts[i][0]))                    txt_save.append(str(pts[i][1]))                 num_txt_i = 0                for txt_i in range(len(txt_save)):                    txt_i = txt_i - num_txt_i                    if txt_save[txt_i] == 'delete':                        for j in range(6):                            del txt_save[txt_i - j]                        num_txt_i += 6                for txt_i in txt_save:                    f.write(str(txt_i) + '\n')                print("txt_save:", txt_save)                break                f.close()                 # 现在是多边形之前的方法不行                # # 查找距离较近的,删除                # points_list = get_list0(txt_path)                # new_points_list = []                # for i in points_list:                #     x0, y0, x1, y1 = i[0], i[1], i[2], i[3]                #     if abs(x1 - x0) > 5 and abs(y1 - y0) > 5:                #         new_points_list.append('(pt1,pt2):')                #         new_points_list.append(x0)                #         new_points_list.append(y0)                #         new_points_list.append(x1)                #         new_points_list.append(y1)                # print(new_points_list)                # file2 = open(txt_path, 'w')                # for i in new_points_list:                #     file2.write(str(i) + '\n')                # file2.close()             # 空格切换至矩形            if POLYLINES == True or w_key == 32:                roi = cv2.selectROI(windowName=WIN_NAME, img=img, showCrosshair=False, fromCenter=False)                x, y, w, h = roi                cv2.rectangle(img=img, pt1=(x, y), pt2=(x + w, y + h), color=(0, 0, 255), thickness=2)                 print('pt1: x = %d, y = %d' % (x, y))                txt_save.append("(pt1,pt2):")                txt_save.append(str(x))                txt_save.append(str(y))                txt_save.append(str(x + w))                txt_save.append(str(y + h))                 # 用红色框显示ROI                # cv2.imshow(WIN_NAME, img)                # cv2.waitKey(0)                 # 保存txt坐标                num_txt_i = 0                for txt_i in range(len(txt_save)):                    txt_i = txt_i - num_txt_i                    if txt_save[txt_i] == 'delete':                        for j in range(6):                            del txt_save[txt_i - j]                        num_txt_i += 6                for txt_i in txt_save:                    f.write(str(txt_i) + '\n')                print("txt_save:", txt_save)                # break                f.close()                 # 查找距离较近的,删除                points_list = get_list0(txt_path)                new_points_list = []                for i in points_list:                    x0, y0, x1, y1 = i[0], i[1], i[2], i[3]                    if abs(x1 - x0) > 5 and abs(y1 - y0) > 5:                        new_points_list.append('(pt1,pt2):')                        new_points_list.append(x0)                        new_points_list.append(y0)                        new_points_list.append(x1)                        new_points_list.append(y1)                print(new_points_list)                file2 = open(txt_path, 'w')                for i in new_points_list:                    file2.write(str(i) + '\n')                file2.close()                break        cv2.destroyAllWindows()     else:        print("输入图片类型错误!请输入JPG/PNG格式的图片!")  if __name__ == '__main__':    # path_file = open('./datasets/drawPath.json', 'r')    path_file = open('./DataSet/drawPath.json', 'r')    path_dic = json.load(path_file)    img_path = path_dic['path']         # # 绘制标准图片的地址    path_file.close()    img_name = img_path.split('\\')[-1][:-4]    define_start(img_name, img_path, 0)

感谢各位的阅读,以上就是“基于OpenCV如何实现动态画矩形和多边形并保存坐标”的内容了,经过本文的学习后,相信大家对基于OpenCV如何实现动态画矩形和多边形并保存坐标这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 基于OpenCV如何实现动态画矩形和多边形并保存坐标

本文链接: https://lsjlt.com/news/352858.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 基于OpenCV实现动态画矩形和多边形并保存坐标
    目录1 画矩形和多边形,模式通过键盘控制2 修改后默认情况下直接画多边形,按鼠标中键切换为画矩形模式现在画矩形和多边形一次只能画一个,还需要修改让其一次可画多个? 1 画矩形和多边形...
    99+
    2023-03-23
    OpenCV绘制矩形 多边形 OpenCV绘制矩形 OpenCV绘制多边形
  • 基于OpenCV如何实现动态画矩形和多边形并保存坐标
    这篇文章主要讲解了“基于OpenCV如何实现动态画矩形和多边形并保存坐标”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于OpenCV如何实现动态画矩形和多边形并保存坐标”吧!1 画矩形和多...
    99+
    2023-07-05
  • 基于Flutter如何实现多边形和多角星组件
    这篇文章主要介绍了基于Flutter如何实现多边形和多角星组件的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇基于Flutter如何实现多边形和多角星组件文章都会有所收获,下面我们一起来看看吧。组件功能正多边形正...
    99+
    2023-06-30
  • 基于C#如何实现多边形冲突检测
    这篇文章主要为大家展示了“基于C#如何实现多边形冲突检测”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“基于C#如何实现多边形冲突检测”这篇文章吧。前言之前在项目上碰到了一个多边形冲突检测的问题,...
    99+
    2023-06-20
  • Html5 Canvas如何实现图片标记、缩放、移动和保存历史状态功能
    这篇文章主要介绍Html5 Canvas如何实现图片标记、缩放、移动和保存历史状态功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!效果预览动图是放cdn的,如果访问不了,可以登录在线尝试尝试: test.algbb...
    99+
    2023-06-09
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作