简体   繁体   English

OpenCV提升了网络摄像头的输入,而不是使用全分辨率

[英]OpenCV upscales webcam's feed instead of using full resolution

I have a 1080p webcam (Logitech v-u0032) and I am creating program that saves still from it's feed every X seconds, however images have black bars on sides and resolution is seemingly lower than still taken with Windows built in camera app, both output file that has 1920x1080 pixels but difference in actual resolution is very visible 我有一个1080p网络摄像头(Logitech v-u0032),我正在创建程序,每隔X秒就可以保存它的进纸,但是图像边上有黑条,分辨率看起来比Windows内置摄像头应用程序还要低,两个输出具有1920x1080像素但实际分辨率不同的文件非常明显

I've searched for ways to change the resolution but OpenCV seems to always upscale to new resolution 我一直在寻找改变分辨率的方法,但OpenCV似乎总是升级到新的分辨率

import cv2
import numpy as np
import datetime
import time
import os

cv2.namedWindow("Unregistered Hypercam")
vc = cv2.VideoCapture(0)

vc.set(3, 1920) # Set the horizontal resolution
vc.set(4, 1080) # Set the vertical resolution
vc.set(5, 10)   # Set the framerate

if vc.isOpened():
    rval, frame = vc.read()
else:
    rval = False

lastSave = time.time()

def mfold(name):
    try:  
         os.mkdir(name)
    except OSError:  
         x = 0
    else:  
        print ("Successfully created the directory %s " % fold)

while rval:
    cv2.imshow("Unregistered Hypercam", frame)
    rval, frame = vc.read()
    now = datetime.datetime.now()

    if time.time() > lastSave + 10:
        lastSave = time.time()
        fold = '\\snapshots\\' # This will create folder C:\snapshots
        mfold(fold)
        cv2.imwrite(fold + str(now.year) + '.' + str(now.month) + '.' + str(now.day) + '  ' + str(now.hour) + 'h_' + str(now.minute) + 'm_' + str(now.second) + 's.png', frame)

    key = cv2.waitKey(20)
    if key == 27:
        break

cv2.destroyWindow("Unregistered Hypercam")

Images are blurry and unsharp with black bars and are nowhere similar to images taken with Windows camera app 黑色条纹图像模糊不清晰,与Windows相机应用程序拍摄的图像无关

Here's an example widget to save webcam/streams into video file or screenshot images. 这是一个将网络摄像头/流保存到视频文件或屏幕截图中的示例窗口小部件。 It keeps the original resolution of the stream. 它保持流的原始分辨率。 I used one of my IP camera streams instead of a webcam but it should work the same with a webcam. 我使用了我的一个IP摄像机流而不是网络摄像头,但它应该与网络摄像头一样。 Currently it opens a stream and saves it as a video but you can modify it to take periodic screenshots. 目前,它会打开一个流并将其保存为视频,但您可以对其进行修改以定期截屏。 Also to modify the resolution, you can manually resize the frame while keeping aspect ratio with this function (it currently is not used in the widget). 另外,要修改分辨率,您可以手动调整帧的大小,同时保持宽高比与此功能(它当前未在小部件中使用)。

Adjust resolution of frame while maintaining aspect ratio 在保持纵横比的同时调整帧的分辨率

# Resizes a image and maintains aspect ratio
def maintain_aspect_ratio_resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    # Grab the image size and initialize dimensions
    dim = None
    (h, w) = image.shape[:2]

    # Return original image if no need to resize
    if width is None and height is None:
        return image

    # We are resizing height if width is none
    if width is None:
        # Calculate the ratio of the height and construct the dimensions
        r = height / float(h)
        dim = (int(w * r), height)
    # We are resizing width if height is none
    else:
        # Calculate the ratio of the 0idth and construct the dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # Return the resized image
    return cv2.resize(image, dim, interpolation=inter)

You can use it like this to adjust width or height 您可以像这样使用它来调整宽度或高度

rval, frame = vc.read()

resize_width = maintain_aspect_ratio_resize(frame, width=500)
resize_height = maintain_aspect_ratio_resize(frame, height=500)

Stream and save video widget 流和保存视频小部件

from threading import Thread
import cv2

class VideoWriterObject(object):
    def __init__(self, src=0):
        # Create a VideoCapture object
        self.capture = cv2.VideoCapture(src)

        # Default resolutions of the frame are obtained (system dependent)
        self.frame_width = int(self.capture.get(3))
        self.frame_height = int(self.capture.get(4))

        # Set up codec and output video settings
        self.codec = cv2.VideoWriter_fourcc('M','J','P','G')
        self.output_video = cv2.VideoWriter('output.avi', self.codec, 30, (self.frame_width, self.frame_height))

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def show_frame(self):
        # Display frames in main program
        if self.status:
            cv2.imshow('frame', self.frame)

        # Press Q on keyboard to stop recording
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            self.output_video.release()
            cv2.destroyAllWindows()
            exit(1)

    def save_frame(self):
        # Save obtained frame into video output file
        self.output_video.write(self.frame)

if __name__ == '__main__':
    video_stream_widget = VideoWriterObject(0)
    while True:
        try:
            video_stream_widget.show_frame()
            video_stream_widget.save_frame()
        except AttributeError:
            pass

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM