opencv十字瞄准线 图像上长按左键画矩形单击右键清除05并保存矩形坐标

 

import copy
import json

import cv2
import numpy as np
import os
import matplotlib.pyplot as plt

WIN_NAME = 'draw_rect'

from win32 import win32gui, win32print
from win32.lib import win32con

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):

    class Rect(object):
        def __init__( self ):
            self.tl = (0, 0)
            self.br = (0, 0)

        def regularize( self ):
            """
            make sure tl = TopLeft point, br = BottomRight point
            """
            pt1 = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1]))
            pt2 = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1]))
            self.tl = pt1
            self.br = pt2

    class DrawRects(object):
        def __init__( self, image, color, thickness=1, center=(10, 10), radius=100 ):
            self.original_image = image
            self.image_for_show = image.copy()
            self.color = color
            self.thickness = thickness
            self.rects = []
            self.current_rect = Rect()
            self.left_button_down = False

            self.center = center
            self.radius = radius

            self.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)

        @staticmethod
        def __clip( value, low, high):
            """
            clip value between low and high
            Parameters
            ----------
            value: a number
                value to be clipped
            low: a number
                low limit
            high: a number
                high limit
            Returns
            -------
            output: a number
                clipped value
            """
            output = max(value, low)
            output = min(output, high)
            return output

        def shrink_point( self, x, y ):
            """
            shrink point (x, y) to inside image_for_show
            Parameters
            ----------
            x, y: int, int
                coordinate of a point
            Returns
            -------
            x_shrink, y_shrink: int, int
                shrinked coordinate
            """
            height, width = self.image_for_show.shape[0:2]
            x_shrink = self.__clip(x, 0, width)
            y_shrink = self.__clip(y, 0, height)
            return (x_shrink, y_shrink)

        if type == 1:
            def getROI( self ):

                roi = image[self.current_rect.tl[1]:self.current_rect.br[1],
                      self.current_rect.tl[0]:self.current_rect.br[0]]

                roi_h = abs(self.current_rect.tl[1] - self.current_rect.br[1])
                roi_w = abs(self.current_rect.tl[0] - self.current_rect.br[0])
                if roi_h > 0 and roi_w > 0:
                    cv2.imwrite(f"./DrawRect/biaozhun/yiwubiaoding/{img_name}.jpg", roi)
                #     cv2.imwrite("J30J_holes.jpg", roi)
                #
                # roi = image[self.current_rect.tl[1]:self.current_rect.br[1],
                #     self.current_rect.tl[0]:self.current_rect.br[0]]
                # cv2.imwrite(f"./DrawRect/biaozhun/yiwubiaoding/{img_name}.jpg", roi)

        def append( self ):
            """
            add a rect to rects list
            """
            self.rects.append(copy.deepcopy(self.current_rect))

        def pop( self ):
            """
            pop a rect from rects list
            """
            rect = Rect()
            if self.rects:
                rect = self.rects.pop()
            return rect

        def reset_image( self ):
            """
            reset image_for_show using original image
            """
            self.image_for_show = self.original_image.copy()

        def draw( self ):
            """
            draw rects on image_for_show
            """
            for rect in self.rects:
                cv2.rectangle(self.image_for_show, rect.tl, rect.br,
                              color=self.color, thickness=self.thickness)

        def draw_current_rect( self ):
            """
            draw current rect on image_for_show
            """
            cv2.rectangle(self.image_for_show,
                          self.current_rect.tl, self.current_rect.br,
                          color=self.color, thickness=self.thickness)

        # 保存结果
        def save_images_rect( self ):
            cv2.imwrite("./DrawRect/biaozhun/imgs/" + img_name + '.jpg', draw_rects.image_for_show)

        def trans_img( self ):
            self.image_for_show_line = np.zeros((image.shape[0], image.shape[1], 3), dtype=np.uint8)

        def draw_crossline( self ):
            self.trans_img()
            pt_left = (self.center[0] - self.radius, self.center[1])
            pt_right = (self.center[0] + self.radius, self.center[1])
            pt_top = (self.center[0], self.center[1] - self.radius)
            pt_bottom = (self.center[0], self.center[1] + self.radius)

            cv2.line(self.image_for_show_line, pt_left, pt_right,
                     (0, 0, 255), self.thickness)
            cv2.line(self.image_for_show_line, pt_top, pt_bottom,
                     (0, 0, 255), self.thickness)

            # cv2.imshow("crossLine", self.image_for_show_line)
            # print("crossline")

    def onmouse_draw_rect( event, x, y, flags, draw_rects ):
        draw_rects.center = (x, y)
        # txt_save = []

        if event == cv2.EVENT_LBUTTONDOWN:
            # pick first point of rect
            print('pt1: x = %d, y = %d' % (x, y))
            txt_save.append("(pt1,pt2):")
            txt_save.append(str(x))
            txt_save.append(str(y))
            # f.write("(pt1,pt2):n" + str(x) + 'n' + str(y) + 'n')
            draw_rects.left_button_down = True
            draw_rects.current_rect.tl = (x, y)

        if draw_rects.left_button_down and event == cv2.EVENT_MOUSEMOVE:
            # pick second point of rect and draw current rect
            draw_rects.current_rect.br = draw_rects.shrink_point(x, y)
            draw_rects.reset_image()
            draw_rects.draw()
            draw_rects.draw_current_rect()
            draw_rects.save_images_rect()

        if event == cv2.EVENT_LBUTTONUP:
            # finish drawing current rect and append it to rects list
            draw_rects.left_button_down = False
            draw_rects.current_rect.br = draw_rects.shrink_point(x, y)
            print('pt2: x = %d, y = %d' % (draw_rects.current_rect.br[0],
                                           draw_rects.current_rect.br[1]))
            # txt_save.append("(pt1,pt2):n")
            txt_save.append(str(draw_rects.current_rect.br[0]))
            txt_save.append(str(draw_rects.current_rect.br[1]))
            # f.write(str(draw_rects.current_rect.br[0]) + 'n' + str(draw_rects.current_rect.br[1]) + 'n')
            draw_rects.current_rect.regularize()
            draw_rects.append()
            draw_rects.getROI()

        if (not draw_rects.left_button_down) and event == cv2.EVENT_RBUTTONDOWN:
            # pop the last rect in rects list
            draw_rects.pop()
            draw_rects.reset_image()
            draw_rects.draw()
            draw_rects.save_images_rect()
            # txt_save = txt_save[:-5]
            txt_save.append('delete')
            # print("clear")

        draw_rects.draw_crossline()
        # return txt_save

    # 根据显示器的大小设置窗口缩放的比例
    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")
        # draw_rects = DrawRects(image, (0, 255, 0), 2, (10, 10), 10000)
        draw_rects = DrawRects(image, (0, 255, 0), num_wh, (10, 10), 10000)

        cv2.namedWindow(WIN_NAME, cv2.WINDOW_NORMAL)
        cv2.namedWindow(WIN_NAME, 2)
        cv2.resizeWindow(WIN_NAME, ratio_w, ratio_h)
        txt_path = "./DrawRect/biaozhun/labels/%s.txt" % (img_name)
        open(txt_path, 'w').close()  # 清空文件数据
        f = open(txt_path, mode='a+')
        txt_save = []
        cv2.setMouseCallback(WIN_NAME, onmouse_draw_rect, draw_rects)  # 画框并保存

        while True:
            # if cv2.getWindowProperty(WIN_NAME, 0) == -1:  # 当窗口关闭时为-1,显示时为0
            #     # print("break")
            #     break

            dest = cv2.add(draw_rects.image_for_show_line, draw_rects.image_for_show)

            # imgplot = plt.imshow(dest)
            # plt.show()
            cv2.imshow(WIN_NAME, dest)

            if cv2.waitKey(1) == 13 or cv2.getWindowProperty(WIN_NAME, 0) == -1:  # enter回车键
                # 保存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()
        cv2.destroyAllWindows()

        # 查找距离较近的,删除
        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()

    else:
        print("输入图片类型错误!请输入JPG/PNG格式的图片!")


if __name__ == '__main__':
    # image = cv2.imread("result.jpg")
    image = cv2.imread("../OpencvCircleLJQ/Images/Final/E_0_9.jpg")
    imagePath ="../OpencvCircleLJQ/Images/Final/E_0_9.jpg"

    define_start("ponits",imagePath, 1)

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>