python 实现一个双目相机启动程序

16 篇文章 0 订阅
4 篇文章 4 订阅

python 实现一个双目相机启动程序(TODO)

对 OpenCV 示例相机启动的程序改写(单线程)(TODO)


import os
import sys
import time

import numpy as np
import cv2 as cv


class IntegratedCamera:
    """ synchronized stereo camera operation """
    def __init__(self, cam_index):
        self.cap = cv.VideoCapture(cam_index)
        self.cap_open_flag = False
        self.camera_properity_dic = {
            "prop_position":cv.CAP_PROP_POS_MSEC,
            "prop_width":cv.CAP_PROP_FRAME_WIDTH,
            "prop_height":cv.CAP_PROP_FRAME_HEIGHT,
            "prop_fps":cv.CAP_PROP_FPS,
            "prop_fourcc":cv.CAP_PROP_FOURCC,
            "prop_format":cv.CAP_PROP_FORMAT,
            "prop_capture_mode":cv.CAP_PROP_MODE,
            "prop_brightness":cv.CAP_PROP_BRIGHTNESS,
            "prop_contrast":cv.CAP_PROP_CONTRAST,
            "prop_saturation":cv.CAP_PROP_SATURATION,
            "prop_hue":cv.CAP_PROP_HUE,
            "prop_gain":cv.CAP_PROP_GAIN,
            "prop_exposure":cv.CAP_PROP_EXPOSURE,
            "prop_bool_auto_exposure":cv.CAP_PROP_AUTO_EXPOSURE,
            "prop_gamma":cv.CAP_PROP_GAMMA,
            "prop_sample_aspect_ratio":cv.CAP_PROP_SAR_NUM,
            "prop_bool_auto_white_balance":cv.CAP_PROP_AUTO_WB,
            "prop_white_balance_temperature":cv.CAP_PROP_WB_TEMPERATURE,
        }


    def get_width(self):
        """ test function """
        return self.cap.get(cv.CAP_PROP_FRAME_WIDTH)

    def get_camera_properity(self, input_properity):
        if input_properity not in [key for key in self.camera_properity_dic.keys()]:
            print("..error_0...properity not found")
            return  # 结束函数
        else:
            return self.cap.get(self.camera_properity_dic[input_properity])

    def set_camera_properity(self, input_properity):
        pass
    
    def set_camera_properity_height_width(self, height=480, width=1280):
        """ property order: height, width  """
        ret_height = self.cap.set(cv.CAP_PROP_FRAME_HEIGHT, height)
        ret_width = self.cap.set(cv.CAP_PROP_FRAME_WIDTH, width)
        if ret_height and ret_height:
            print("set resolution :: height={0}, width={1}".format(height, width))
        else:
            print("..error_3...set resolution failed")

    def start_camera(self):
        if not self.cap.isOpened():
            print("..error_2...cannot open camera")
            self.cap_open_flag = False
            return self.cap_open_flag

        self.cap_open_flag = True
        return self.cap_open_flag

    def get_frame(self, enable_line="", line_num=3):
        ret, frame = self.cap.read()
        if not ret:
            print("..error_1...frame not grabbed")
            return
        
        height, width = frame.shape[:2]
        frame_left = frame[:, int(width/2):]
        frame_right = frame[:, :int(width/2)]

        if enable_line == "true":
            # enable_line = True
            
            fame = self.draw_line(frame, line_num)
            fame_left = self.draw_line(frame_left, line_num)
            fame_right = self.draw_line(frame_right, line_num)
        
        return frame, frame_left, frame_right

    def draw_line(self, input_frame, line_num):
        height, width = input_frame.shape[:2]

        interval = int(height/(line_num+1))
        height_accumulate = 0
        for i in range(line_num):
            if height_accumulate == height:
                break
            
            height_accumulate += interval
            input_frame = cv.line(input_frame, (0, height_accumulate), (width, height_accumulate), (0, 0, 255), 1)

        return input_frame


    def close_camera(self):
        self.cap.release()
        self.cap_open_flag = False
        cv.destroyAllWindows()


if __name__ == "__main__":
    # import cv2 as cv

    ic = IntegratedCamera(0)

    save_path = r".\image_save"

    # ic.set_camera_properity_height_width(480, 1280)
    ic.set_camera_properity_height_width(1520, 3040)
    start_flag = ic.start_camera()

    height = ic.get_camera_properity("prop_height")
    width = ic.get_camera_properity("prop_width")
    print("get resolution :: height={0}, width={1}".format(height, width))

    save_img_count = 0
    frame_interval = 33  # 33ms
    while start_flag:
        frame, frame_left, frame_right = ic.get_frame("true", 15)
        
        cv.namedWindow("frame", cv.WINDOW_KEEPRATIO)
        cv.namedWindow("frame_left", cv.WINDOW_KEEPRATIO)
        cv.namedWindow("frame_right", cv.WINDOW_KEEPRATIO)

        cv.imshow("frame", frame)
        cv.imshow("frame_left", frame_left)
        cv.imshow("frame_right", frame_right)

        if cv.waitKey(frame_interval) == ord('q'):  # change to 33ms = 30fps
            print("camera exit with q")
            break
        elif cv.waitKey(frame_interval) == ord('s'):
            print("frame save with s")
            if not os.path.exists(save_path):
                os.mkdir(save_path)
            cv.imwrite(save_path + r"\{}.png".format(save_img_count), frame)
            save_img_count += 1

    ic.close_camera()

多线程相机启动(TODO)

from threading import Thread
import cv2, time
import sys


class VideoStreamWidget(object):
    def __init__(self, src=0, fps=30):
        """ init the device with device index(=0) and fps(=30)"""
        self.frame_delay = int((1/fps)*1000)

        self.capture = cv2.VideoCapture(src)
        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True  # set self.thread as daemon thread so when program quits, daemon threads are killed automatically
        self.thread.start()

        self.save_count = 0
        # self.frame_count = 0

    def update(self):
        # Read the next frame from the stream in a different thread
        frame_count = 0
        start = time.perf_counter()
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()
                # print(self.frame)                
                frame_count += 1

                end = time.perf_counter()
                seconds = end - start
                fps = frame_count / seconds
                print(frame_count, " ", fps)

                frame_count = 0
                start = time.perf_counter()
            time.sleep(.01)  # interval between each frame .01 sec

    def show_frame(self):
        # Display frames in main program
        IMG_SAVE_PATH = r".\image_save"
        
        # start = time.perf_counter()

        cv2.imshow('frame', self.frame)
        key = cv2.waitKey(self.frame_delay)  # control the frame interval
        if key == ord('q'):
            self.capture.release()
            cv2.destroyAllWindows()
            exit(0)  # exit with success
        if key == ord('s'):
            cv2.imwrite(IMG_SAVE_PATH + "\{}.jpg".format(self.save_count), self.frame)
            print("save with s {0}".format(self.save_count))
            self.save_count += 1

        # end = time.perf_counter()
        # seconds = end - start
        # fps = self.frame_count / seconds
        # print("fps = {}".format(fps))

if __name__ == '__main__':
    video_stream_widget = VideoStreamWidget(0, 1)
    while True:
        try:
            # start = time.perf_counter()
            video_stream_widget.show_frame()
            # end = time.perf_counter()
            # seconds = end - start

        except AttributeError:
            pass
        # video_stream_widget.show_frame()

多线程相机启动(无 try catch)(TODO)

from threading import Thread
import time
import sys
import cv2
import numpy as np


class VideoStreamWidget(object):
    def __init__(self, src=0, fps=30):
        """ init the device with device index(=0) and fps(=30)"""
        self.frame_delay = int((1/fps)*1000)  # miniseconds
        # self.capture = cv2.VideoCapture(src, cv2.CAP_DSHOW)
        self.capture = cv2.VideoCapture(src)

        print("device name :: {0}".format(self.capture.getBackendName()))  # ???
        # self.capture.get()

        self._init_sys_params()
        # self.frame = None
        # self.status = None
        self._init_frame()
        # Start the thread to read frames from the video stream in background
        # self.thread = Thread(target=self._update, args=())
        # self.thread.daemon = True  # set self.thread as daemon thread so when program quits, daemon threads are killed automatically
        # self.thread.start()
        self.thread = None
        self.save_count = 0
        self.fps_show = 0
        # self.frame_count = 0

    def _init_frame(self):
        width = self.get_camera_properity("prop_width")
        height = self.get_camera_properity("prop_height")
        self.frame = np.zeros((int(height), int(width), 3), np.uint8)
        self.status = None

    def start_daemon_thread(self):
        # Start the thread to read frames from the video stream in background
        self.thread = Thread(target=self._update, args=())
        self.thread.daemon = True  # set self.thread as daemon thread so when program quits, daemon threads are killed automatically
        self.thread.start()

    def _init_sys_params(self):
        self.camera_properity_dic = {
            "prop_width":cv2.CAP_PROP_FRAME_WIDTH,
            "prop_height":cv2.CAP_PROP_FRAME_HEIGHT,
            "prop_fps":cv2.CAP_PROP_FPS,
            "prop_fourcc":cv2.CAP_PROP_FOURCC,
            "prop_brightness":cv2.CAP_PROP_BRIGHTNESS,
            "prop_contrast":cv2.CAP_PROP_CONTRAST,
            "prop_exposure":cv2.CAP_PROP_EXPOSURE,
            "prop_bool_auto_exposure":cv2.CAP_PROP_AUTO_EXPOSURE,
        }
        self.error_dic = {
            "error_0":"properity not found",
            "error_1":"frame not grabbed",
            "error_2":"cannot open camera",
            "error_3":"set resolution failed",
            "error_4":"properity value is none",
        }

    def _update(self):  # daemon thread
        # start background frame grabbing, daemon thread
        # Read the next frame from the stream in a different thread
        # frame_count = 0
        start = time.perf_counter()
        while True:
            if self.capture.isOpened():
                # (self.status, self.frame) = self.capture.read()
                (self.status, self.frame) = self.capture.read()
                # print(self.frame)                
                # frame_count += 1
                end = time.perf_counter()
                seconds = end - start
                fps = 1 / seconds
                print("[update] fps = {0}".format(fps))
                frame_count = 0
                start = time.perf_counter()
                # cv2.imshow("update_frame", self.frame)
            else:
                print("..{0}...{1}".format("error_2 on [_update]", self.error_dic["error_2"]))
                # exit(1)
                # sys.exit("..{0}...{1}".format("error_2", self.error_dic["error_2"]))  # daemon thread not exit main program
            time.sleep(.01)  # interval between each frame .01 sec for main thread (?)
            # cv2.waitKey(1)
            # cv2.destroyAllWindows()

    def show_frame(self, enable_fun=False, enable_text=False, enable_line=False):
        # Display frames in main program, main thread
        # if not enable_fun:
        #     return False
        IMG_SAVE_PATH = r".\image_save"
        start = time.perf_counter()
        # self.fps_show = 0
        if enable_text:
            self._put_text(self.frame, self.fps_show)
        if enable_line:
            self._draw_line_by_pix(self.frame)
        cv2.namedWindow('show_frame', cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)
        cv2.imshow('show_frame', self.frame)
        key = cv2.waitKey(self.frame_delay)  # control the frame interval
        if key == ord('q'):
            # self.capture.release()
            # cv2.destroyAllWindows()
            cv2.destroyWindow('show_frame')
            exit(0)  # exit with success
            return False
        if key == ord('s'):
            cv2.imwrite(IMG_SAVE_PATH + "\{}.png".format(self.save_count), self.frame)
            print("save with s {0}".format(self.save_count))
            self.save_count += 1
        end = time.perf_counter()
        seconds = end - start
        self.fps_show = 1 / seconds
        print("--[show] fps = {0}".format(self.fps_show), seconds, self.frame_delay)
        start = time.perf_counter()

    def _put_text(self, input_frame, input_fps=0):
        text = "fps={0}".format(input_fps)
        # org = (input_frame.shape[0], 0)
        # print(input_frame.shape[0], input_frame.shape[1])  # 960, 960
        org = (50, 150)
        cv2.putText(input_frame, text, org, cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 2)

    def _draw_line(self, input_frame, line_num):
        """ depricated, use _draw_line_by_pix instead """
        height, width = input_frame.shape[:2]
        interval = int(height/(line_num+1))
        height_accumulate = 0
        for i in range(line_num):
            if height_accumulate == height:
                break
            height_accumulate += interval
            input_frame = cv2.line(input_frame, (0, height_accumulate), (width, height_accumulate), (0, 0, 255), 1)
        return input_frame

    def _draw_line_by_pix(self, input_frame):
        """ draw line at very 40 pix point of image height """
        # print("input_frame.shape[0]={0}, input_frame.shape[1]={1}".format(input_frame.shape[0], input_frame.shape[1]))
        for i in range(0, input_frame.shape[0], 40):
            # print("i={0}".format(i))
            cv2.line(input_frame, (0, i), (input_frame.shape[1], i), (0, 0, 255), 1)

    def get_all_properities(self):
        """ return all camera properity """
        print("="*40)
        for prop_key, prop_value in self.camera_properity_dic.items():
            print("{0} :: {1}".format(prop_key, self.capture.get(prop_value)))
        print("="*40)

    def get_camera_properity(self, input_properity):
        if input_properity not in [key for key in self.camera_properity_dic.keys()]:
            # print("..error_0...properity not found")
            print("..{0}...{1}".format("error_0", self.error_dic["error_0"]))
            return  # 结束函数
        else:
            return self.capture.get(self.camera_properity_dic[input_properity])

    def set_camera_properity(self, input_properity, value):
        """ set a new cam. prop. to overwrite its old value """
        if input_properity not in [key for key in self.camera_properity_dic.keys()]:
            # print("..error_0...properity not found")
            print("..{0}...{1}".format("error_0", self.error_dic["error_0"]))
            return
        elif value is None:
            print("..{0}...{1}".format("error_4", self.error_dic["error_4"]))
            return
        else:
            return self.capture.set(self.camera_properity_dic[input_properity], value)


def _main():

    video_stream_widget = VideoStreamWidget(0, 30)
    # print("device name :: {0}".format(video_stream_widget.get))
    
    # video_stream_widget.set_camera_properity("prop_height", 1520)  # 720
    # video_stream_widget.set_camera_properity("prop_width", 3040)  # 2560
    video_stream_widget.set_camera_properity("prop_height", 720)  # 720
    video_stream_widget.set_camera_properity("prop_width", 2560)  # 2560
    video_stream_widget.get_all_properities()

    video_stream_widget.start_daemon_thread()

    while True:
        # continue  # 保证 update 线程运行
        
        # show_frame_flag = False
        # key = cv2.waitKey(1)

        # try:
        #     # start = time.perf_counter()
        #     # if key == ord('r'):
        #     #     print("r pressed")
        #     #     show_frame_flag = True

        #     video_stream_widget.show_frame(enable_text=True, enable_line=True)
            
        #     # show_frame_flag = video_stream_widget.show_frame(enable_text=True)  # show_frame 线程运行
        #     # # end = time.perf_counter()
        #     # seconds = end - start
        #     # fps = 1 / seconds
        #     # print("fps = {}".format(fps), seconds)
        #     # start.time.perf_counter()
        #     # if stop_flag:  # 这种
        #     #     break

        # except AttributeError:
        #     pass

        video_stream_widget.show_frame(enable_text=True, enable_line=True)  # now no need of try: catch


if __name__ == "__main__":
    _main()


"""
1. deque
2. enumerate camera
3. return camera name
4. opencv face detect
5. dlib face detect
6. stereo calibrate
7. depth map
8. pcd viewer
9. point cloud processing
"""

单线程协程启动(TODO)

####################################################################################
########## using coroutine 协程 完成相机图像显示
####################################################################################
import cv2
import numpy as np
import time


def put_text(input_frame, input_fps=0, input_fps_max=0):
    text = "fps={0:.3f}, fps_max={1:.3f}".format(input_fps, input_fps_max)
    org = (50, 150)
    cv2.putText(input_frame, text, org, cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 2)


def consume_frame():
    """ generator """
    msg_to_producer = ''
    frameNum_c = 1
    fps_max = 0
    while True:
        # frame_c = yield msg_to_producer
        start_t = time.perf_counter()
        package = yield msg_to_producer
        end_t = time.perf_counter()
        total_t = end_t - start_t
        fps = 1 / total_t
        if fps > fps_max:
            fps_max = fps
        # print("fps :: {:.3f}".format(fps))
        frame_c = package[1]
        put_text(frame_c, fps, fps_max)
        print("np.shape(frame) :: {}".format(np.shape(frame_c)))
        # if not frame:
        if frame_c.all() == None:
            print("frame_c == None")
            return  # return None
        print("[CONSUMER] frame_num :: {}".format(frameNum_c))
        cv2.namedWindow("image consumer")
        cv2.imshow("image consumer", frame_c)
        frameNum_c += 1
        msg_to_producer = "frame ok"
        key = cv2.waitKey(1)  # waitKey position in producer or consumer has 10 fps difference, latter is greater 
        if key == ord('q'):
            package[0].release()  # ourceReaderCB::~SourceReaderCB terminating async callback
            cv2.destroyAllWindows()
    

def produce_frame(c):
    """ caller """
    c.send(None)
    frameNum_p = 1
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)  # 这个模式没有 terminating async callback warning
    # cap = cv2.VideoCapture(0)
    height = 1520
    width = 3040
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
    while cap.isOpened():
        start = time.perf_counter()
        ret_val, frame_p = cap.read()
        end = time.perf_counter()
        total = end - start
        fps = 1 / total
        print("fps :: {:.3f}".format(fps))
        if not ret_val:
            continue
        print("ret_val :: {}".format(ret_val))
        print("[PRODUCER] frame_num :: {}".format(frameNum_p))
        frameNum_p += 1
        msg_from_consumer = c.send((cap, frame_p))
        print("[PRODUCER] comsumer return :: {}".format(msg_from_consumer))
        # key = cv2.waitKey(1)
        # if key == ord('q'):
        #     cap.release()  # ourceReaderCB::~SourceReaderCB terminating async callback
        #     cv2.destroyAllWindows()
    c.close()
        

c = consume_frame()
produce_frame(c)

参考

链接1: Recording video with Opencv Python Multithreading
链接2: Daemon is not daemon, but what is it?
链接3: python daemon=True有什么作用?
链接4: python中exit()的用法
链接5: How to capture multiple camera streams with OpenCV?
链接6: Python OpenCV streaming from camera - multithreading, timestamps
链接7: Multithreading with OpenCV-Python to improve video processing performance(TODO)
链接8: Increasing webcam FPS with Python and OpenCV(TODO)
链接9: 高性能Python之:Queue,deque,queue对比
链接10: 简析Python中的四种队列
链接11: threading — Thread-based parallelism
链接12: python3 queue的多线程通信
链接13: 多线程
链接14: Attribute Error
链接15: link
链接16: link
链接17: link
链接18: link
链接19: link

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值