在OpenCV中放大后,Python会捕捉图像的特定部分 [英] Python capture a specific part of an image after zooming in OpenCV

查看:0
本文介绍了在OpenCV中放大后,Python会捕捉图像的特定部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我尝试使用我的网络摄像头进行放大和缩小,并在缩放后捕捉实时网络摄像头中特定部分的图像。但是,我可以放大和缩小,但通过使用";cam.read()";,我只能捕获整个图像,而不能捕获我已缩放的图像的特定部分。我已经定义了ROI,但现在的问题是ROI正在工作,但我无法使图像放大或缩小。我似乎找不到问题所在。

import cv2
import time
import os
import datetime
from threading import Thread
from queue import Queue
import numpy as np
import imutils
from PIL import Image


class Camera:
    def __init__(self, mirror=False):
        self.data = None
        self.cam = cv2.VideoCapture(0,  cv2.CAP_DSHOW)

        self.WIDTH = 640
        self.HEIGHT = 480

        self.center_x = self.WIDTH / 2
        self.center_y = self.HEIGHT / 2
        self.touched_zoom = False

        self.image_queue = Queue()
        self.video_queue = Queue()

        self.scale = 1
        self.__setup()

        self.recording = False
        self.image_coordinates = []
        self.extract = False
        self.selected_ROI = False

        self.select_roi()

        self.mirror = mirror

    def __setup(self):
        self.cam.set(cv2.CAP_PROP_FRAME_WIDTH, self.WIDTH)
        self.cam.set(cv2.CAP_PROP_FRAME_HEIGHT, self.HEIGHT)
        time.sleep(2)

    def get_location(self, x, y):
        self.center_x = x
        self.center_y = y
        self.touched_zoom = True

    def stream(self):

        def streaming():

            self.ret = True
            while self.ret:
                self.ret, np_image = self.cam.read()
                if np_image is None:
                    continue
                if self.mirror:

                    np_image = cv2.flip(np_image, 1)
                if self.touched_zoom:
                    np_image = self.__zoom(np_image, (self.center_x, self.center_y))
                else:
                    if not self.scale == 1:
                        np_image = self.__zoom(np_image)
                self.data = np_image
                k = cv2.waitKey(1)
                if k == ord('q'):
                    self.release()
                    break

        Thread(target=streaming).start()

    def __zoom(self, img, center=None):

        height, width = img.shape[:2]
        if center is None:

            center_x = int(width / 2)
            center_y = int(height / 2)
            radius_x, radius_y = int(width / 2), int(height / 2)
        else:

            rate = height / width
            center_x, center_y = center


            if center_x < width * (1-rate):
                center_x = width * (1-rate)
            elif center_x > width * rate:
                center_x = width * rate
            if center_y < height * (1-rate):
                center_y = height * (1-rate)
            elif center_y > height * rate:
                center_y = height * rate

            center_x, center_y = int(center_x), int(center_y)
            left_x, right_x = center_x, int(width - center_x)
            up_y, down_y = int(height - center_y), center_y
            radius_x = min(left_x, right_x)
            radius_y = min(up_y, down_y)


        radius_x, radius_y = int(self.scale * radius_x), int(self.scale * radius_y)


        min_x, max_x = center_x - radius_x, center_x + radius_x
        min_y, max_y = center_y - radius_y, center_y + radius_y


        cropped = img[min_y:max_y, min_x:max_x]

        new_cropped = cv2.resize(cropped, (width, height), interpolation=cv2.INTER_CUBIC)

        return new_cropped

    def touch_init(self):
        self.center_x = self.WIDTH / 2
        self.center_y = self.HEIGHT / 2
        self.touched_zoom = False
        self.scale = 1

    def zoom_out(self):

        if self.scale < 1:
            self.scale += 0.1
        if self.scale == 1:
            self.center_x = self.WIDTH
            self.center_y = self.HEIGHT
            self.touched_zoom = False

    def zoom_in(self):

        if self.scale > 0.2:
            self.scale -= 0.1

    def zoom(self, num):
        if num == 0:
            self.zoom_in()
        elif num == 1:
            self.zoom_out()
        elif num == 2:
            self.touch_init()


    def save_picture(self):


        ret, img = self.cam.read()
        if ret:
            now1 = datetime.datetime.now()
            now_str1 = now1.strftime("%Y-%m-%d-%H-%M-%S")
            outfilename1 = 'Img-{}.jpg'.format(now_str1)
            path = 'C:/Users/dashi/Documents/MyRiV/espeyh_images'
            cv2.imwrite(os.path.join(path, outfilename1), img)
            path1 = ('C:/Users/dashi/Documents/MyRiV/espeyh_images/' + outfilename1)

            imag = cv2.imread(path1)
            lower = np.array([140, 140, 140])
            upper = np.array([255, 255, 255])
            thresh = cv2.inRange(imag, lower, upper)
            kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (26, 30))
            morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
            mask = 255 - morph
            result = cv2.bitwise_and(imag, imag, mask=mask)
            cv2.imshow('Background Removed', result)
            outfilename2 = 'Img-{}.jpg'.format(now_str1)
            path2 = ('C:/Users/dashi/Documents/MyRiV/modified_images')
            cv2.imwrite(os.path.join(path2, outfilename2), result)


    def record_video(self):

        fc = 20.0
        record_start_time = time.time()
        now = datetime.datetime.now()
        date = now.strftime('%Y%m%d')
        t = now.strftime('%H')
        num = 1
        filename = 'C:/Users/dashi/Documents/MyRiV/espeyh_videos/captured_{}_{}.avi'.format(date, t, num)
        while os.path.exists(filename):
            num += 1
            filename = 'videos/captured_{}_{}_{}.avi'.format(date, t, num)
        codec = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
        out = cv2.VideoWriter(filename, codec, fc, (int(self.cam.get(3)), int(self.cam.get(4))))
        while self.recording:
            if time.time() - record_start_time >= 600:
                self.record_video()
                break
            ret, frame = self.cam.read()
            if ret:
                if len(os.listdir('C:/Users/dashi/Documents/MyRiV/espeyh_videos')) >= 100:
                    name = self.video_queue.get()
                    if os.path.exists(name):
                        os.remove(name)
                out.write(frame)
                self.video_queue.put_nowait(filename)
            k = cv2.waitKey(1)
            if k == ord('q'):
                break

    def crop_ROI(self):
        if self.selected_ROI:
            self.cropped_image = self.frame.copy()

            x1 = self.image_coordinates[0][0]
            y1 = self.image_coordinates[0][1]
            x2 = self.image_coordinates[1][0]
            y2 = self.image_coordinates[1][1]

            self.cropped_image = self.cropped_image[y1:y2, x1:x2]

            print('Cropped image: {} {}'.format(self.image_coordinates[0], self.image_coordinates[1]))
        else:
            print('Select ROI to crop before cropping')

    def show_cropped_ROI(self):
        cv2.imshow('cropped image', self.cropped_image)

    def select_roi(self):
        while True:
            if self.cam.isOpened():
                # Read frame
                (self.status, self.frame) = self.cam.read()
                cv2.imshow('image', self.frame)
                key = cv2.waitKey(2)

                # Crop image
                if key == ord('c'):
                    self.clone = self.frame.copy()
                    cv2.namedWindow('image')
                    cv2.setMouseCallback('image', self.mouse_callback)
                    while True:
                        key = cv2.waitKey(2)
                        cv2.imshow('image', self.clone)

                        # Crop and display cropped image
                        if key == ord('c'):
                            self.crop_ROI()
                            self.show_cropped_ROI()

                        # Resume video
                        if key == ord('r'):
                            break
                # Close program with keyboard 'q'
                if key == ord('q'):
                    cv2.destroyAllWindows()
                    exit(1)
            else:
                pass

    def show(self):
        while True:
            frame = self.data
            if frame is not None:
                cv2.imshow('Zooming', frame)
                cv2.setMouseCallback('Zooming', self.mouse_callback)
            key = cv2.waitKey(1)
            if key == ord('f'):
                if key == ord('q'):
                    self.release()
                    cv2.destroyAllWindows()
                    break

                elif key == ord('z'):

                    self.zoom_in()

                elif key == ord('x'):

                    self.zoom_out()

                elif key == ord('p'):

                    self.save_picture()

                elif key == ord('v'):

                    self.touch_init()

                elif key == ord('r'):

                    self.recording = not self.recording
                    if self.recording:
                        t = Thread(target=cam.record_video)
                        t.start()


            elif key == ord('k'):
                self.select_roi()

    def release(self):
        self.cam.release()
        cv2.destroyAllWindows()

    def mouse_callback(self, event, x, y, flag, parameters):
        if event == cv2.EVENT_LBUTTONDBLCLK:
            self.get_location(x, y)
            self.zoom_in()
        elif event == cv2.EVENT_RBUTTONDOWN:
            self.zoom_out()
        elif event == cv2.EVENT_LBUTTONDOWN:
            self.image_coordinates = [(x,y)]
            self.extract = True
        elif event == cv2.EVENT_LBUTTONUP:
            self.image_coordinates.append((x,y))
            self.extract = False

            self.selected_ROI = True

            # Draw rectangle around ROI
            cv2.rectangle(self.clone, self.image_coordinates[0], self.image_coordinates[1], (0,255,0), 2)
        elif event == cv2.EVENT_RBUTTONDOWN:
            self.clone = self.frame.copy()
            self.selected_ROI = False



if __name__ == '__main__':
    cam = Camera(mirror=True)
    cam.stream()
    cam.show()

推荐答案

您应该像裁剪显示器一样裁剪正在录制的图像。

此外,您正在从2个线程读取视频捕获。我认为这不是一个好主意:您可能正在显示和录制一个超过2的图像。(第一个图像显示,第二个图像录制,第三个图像显示,...)。

您应该只在一个位置调用self.cam.read(),根据需要裁剪图像,并使其既可用于显示又可用于录制。

这篇关于在OpenCV中放大后,Python会捕捉图像的特定部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆