【python脚本】在图像中标注目标,并保存结果

说明
【功能】在图像中用鼠标拖一个矩形,并将这个矩形框的像素坐标保存到文件
【输入参数】

  • image_path: 图像的根路径
  • output_file: 输出文件路径,如 /xx/xx/res.txt
import argparse
import cv2
import os

class RectangularSelection:
    def __init__(self, image_path, output_file):
        self.image_path = image_path
        self.output_file = output_file

    def run(self):
        # 1. check and prepare
        if not os.path.exists(self.image_path):
            print('\33[31mError: invalid image path "{}"\33[0m'.format(self.image_path))
            return
        ofs = open(self.output_file, 'w')

        # 2. traverse and save result to file
        names = self.obtain_file_names(self.image_path, 'jpg')
        # print(names)
        for timestamp, name in names:
            exit = self.click_rectangle(timestamp, name)
            if exit == True:
                break

            # check and save result
            if len(self.rec_pts) > 0 and len(self.rec_pts) % 2 == 0:
                while True:
                    check = self.check_rectangle(timestamp, name)
                    if check == True:
                        ofs.write(str(timestamp))
                        for pt in self.rec_pts:
                            ofs.write(" " + str(pt[0]) + " " + str(pt[1]))
                        ofs.write("\n")
                        break
                    else:
                        exit = self.click_rectangle(timestamp, name)
                        if exit == True:
                            exit(0)

    def obtain_file_names(self, image_path, suffix):
        res = []
        for _, _, names in os.walk(image_path):
            names.sort(key=lambda n: int(n.split('.')[0]))
            for name in names:
                if name.split('.')[-1] == suffix:
                    res.append(((float(name.split('.')[0]) / 1e6), os.path.join(image_path, name)))
            break
        return res

    def click_and_crop(self, event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            self.rec_pts.append((x, y))
        elif event == cv2.EVENT_LBUTTONUP:
            self.rec_pts.append((x, y))
            # draw a rectangle around the region of interest
            if len(self.rec_pts) >= 2:
                cv2.rectangle(self.image, self.rec_pts[-2], self.rec_pts[-1], (0, 255, 0), 2)
                cv2.imshow("image", self.image)

    def click_rectangle(self, timestamp, name):
        exit = False
        self.image = cv2.imread(name)
        clone = self.image.copy()
        cv2.namedWindow("image")
        cv2.setMouseCallback("image", self.click_and_crop)
        self.rec_pts = []
        while True:
            cv2.putText(self.image, str(timestamp), (5,50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
            cv2.putText(self.image, "please click left top and right bottom (c: ok and next, q: exit)", (5,100),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
            cv2.imshow("image", self.image)
            key = cv2.waitKey(1) & 0xFF
            if key == ord("r"):
                self.image = clone.copy()
                self.rec_pts = []
            elif key == ord("c"):
                break
            elif key == ord("q"):
                exit = True
                break
        cv2.destroyAllWindows()
        return exit

    def check_rectangle(self, timestamp, name):
        check = False
        cv2.namedWindow("check")
        img = cv2.imread(name)
        for i in range(0, len(self.rec_pts), 2):
            cv2.rectangle(img, self.rec_pts[i], self.rec_pts[i + 1], (0, 0, 255), 2)
        while True:
            cv2.putText(img, str(timestamp), (5,50), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
            cv2.putText(img, "please check (c: ok and next, x: do it again)", (5,100),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
            cv2.imshow("check", img)
            key = cv2.waitKey(1) & 0xFF
            if key == ord("c"):
                check = True
                break
            elif key == ord("x"):
                check = False
                break
        return check

if __name__=="__main__":
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--image_path", required=True, help="Path to the image")
    ap.add_argument("-o", "--output_file", required=True, help="output_path")
    args = ap.parse_args()

    rec_select = RectangularSelection(args.image_path, args.output_file)
    rec_select.run()
这个任务需要用到机器学习和图像处理的知识,需要用到一些 Python 库来实现,比如 TensorFlow,Keras,OpenCV 等。下面是一个基本的示例代码: ```python import numpy as np import cv2 from keras.models import Sequential from keras.layers.convolutional import Conv2D, MaxPooling2D from keras.layers import Dense, Dropout, Flatten from keras.optimizers import Adam # 加载训练数据和标签 training_data = np.load('training_data.npy') training_labels = np.load('training_labels.npy') # 将训练数据和标签进行归一化处理 training_data = training_data.astype('float32') / 255 training_labels = training_labels.astype('float32') # 创建卷积神经网络模型 model = Sequential() model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(50, 50, 1))) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(10, activation='softmax')) # 编译模型 model.compile(loss='categorical_crossentropy', optimizer=Adam(lr=0.001), metrics=['accuracy']) # 训练模型 model.fit(training_data, training_labels, epochs=10, batch_size=32) # 加载验证码图片进行预测 captcha_image = cv2.imread('captcha.png', cv2.IMREAD_GRAYSCALE) captcha_image = cv2.resize(captcha_image, (50, 50)) captcha_image = captcha_image.astype('float32') / 255 captcha_image = captcha_image.reshape((1, 50, 50, 1)) # 预测验证码 prediction = model.predict(captcha_image) # 输出预测结果 print(prediction) ``` 这个示例代码需要两个文件:`training_data.npy` 和 `training_labels.npy`,用于训练模型。你需要自己收集图片数据和标签,并将其转换为 numpy 数组格式保存。同时,你也需要自己手动标注验证码图片的标签。 这个示例代码只是一个基本的框架,还需要根据实际情况进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值