最近想做实时目标检测,需要用到python开启摄像头,我手上只有两个uvc免驱的摄像头,性能一般。利用python开启摄像头费了一番功夫,主要原因是我的摄像头都不能用cv2的VideCapture打开,这让我联想到原来opencv也打不开Android手机上的摄像头(后来采用QML的Camera模块实现的)。看来opencv对于摄像头的兼容性仍然不是很完善。
我尝了几种办法:v4l2,v4l2_capture以及simpleCV,都打不开。最后采用pygame实现了摄像头的采集功能,这里直接给大家分享具体实现代码(python3.6,cv2,opencv3.3,ubuntu16.04)。中间注释的部分是我上述方法打开摄像头的尝试,说不定有适合自己的。
import pygame.cameraimport timeimport pygameimport cv2import numpy as np def surface_to_string(surface): """convert pygame surface into string""" return pygame.image.tostring(surface, 'RGB') def pygame_to_cvimage(surface): """conver pygame surface into cvimage""" #cv_image = np.zeros(surface.get_size, np.uint8, 3) image_string = surface_to_string(surface) image_np = np.fromstring(image_string, np.uint8).reshape(480, 640, 3) frame = cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB) return image_np, frame pygame.camera.init()pygame.camera.list_cameras()cam = pygame.camera.Camera("/dev/video0", [640, 480]) cam.start()time.sleep(0.1)screen = pygame.display.set_mode([640, 480]) while True: image = cam.get_image() cv_image, frame = pygame_to_cvimage(image) screen.fill([0, 0, 0]) screen.blit(image, (0, 0)) pygame.display.update() cv2.imshow('frame', frame) key = cv2.waitKey(1) if key & 0xFF == ord('q'): break #pygame.image.save(image, "pygame1.jpg") cam.stop()
上述代码需要注意一个地方,就是pygame图片和opencv图片的转化(pygame_to_cvimage)有些地方采用cv.CreateImageHeader和SetData来实现,注意这两个函数在opencv3+后就消失了。因此采用numpy进行实现。
from imutils.video import FPSimport argparseimport imutils import v4l2import fcntl import v4l2captureimport selectimport image import pygame.cameraimport pygameimport cv2import numpy as npimport time def surface_to_string(surface): """convert pygame surface into string""" return pygame.image.tostring(surface, 'RGB') def pygame_to_cvimage(surface): """conver pygame surface into cvimage""" #cv_image = np.zeros(surface.get_size, np.uint8, 3) image_string = surface_to_string(surface) image_np = np.fromstring(image_string, np.uint8).reshape(480, 640, 3) frame = cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB) return frame ap = argparse.ArgumentParser()ap.add_argument("-p", "--prototxt", required=True, help="path to caffe deploy prototxt file")ap.add_argument("-m", "--model", required=True, help="path to caffe pretrained model")ap.add_argument("-c", "--confidence", type=float, default=0.2, help="minimum probability to filter weak detection")args = vars(ap.parse_args()) CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3)) print("[INFO] loading model...")net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"]) print("[INFO] starting video stream ...") ###### opencv #########vs = VideoStream(src=1).start()##camera = cv2.VideoCapture(0)#if not camera.isOpened():# print("camera is not open")#time.sleep(2.0) ###### v4l2 ######## #vd = open('/dev/video0', 'r')#cp = v4l2.v4l2_capability()#fcntl.ioctl(vd, v4l2.VIDIOC_QUERYCAP, cp) #cp.driver ##### v4l2_capture#video = v4l2capture.Video_device("/dev/video0")#size_x, size_y = video.set_format(640, 480, fourcc= 'MJPEG')#video.create_buffers(30) #video.queue_all_buffers() #video.start() ##### pygame ####pygame.camera.init()pygame.camera.list_cameras()cam = pygame.camera.Camera("/dev/video0", [640, 480]) cam.start()time.sleep(1) fps = FPS().start() while True: #try: # frame = vs.read() #except: # print("camera is not opened") #frame = imutils.resize(frame, width=400) #(h, w) = frame.shape[:2] #grabbed, frame = camera.read() #if not grabbed: # break #select.select((video,), (), ()) #frame = video.read_and_queue() #npfs = np.frombuffer(frame, dtype=np.uint8) #print(len(npfs)) #frame = cv2.imdecode(npfs, cv2.IMREAD_COLOR) image = cam.get_image() frame = pygame_to_cvimage(image) frame = imutils.resize(frame, width=640) blob = cv2.dnn.blobFromImage(frame, 0.00783, (640, 480), 127.5) net.setInput(blob) detections = net.forward() for i in np.arange(0, detections.shape[2]): confidence = detections[0, 0, i, 2] if confidence > args["confidence"]: idx = int(detections[0, 0, i, 1]) box = detections[0, 0, i, 3:7]*np.array([640, 480, 640, 480]) (startX, startY, endX, endY) = box.astype("int") label = "{}:{:.2f}%".format(CLASSES[idx], confidence*100) cv2.rectangle(frame, (startX, startY), (endX, endY), COLORS[idx], 2) y = startY - 15 if startY - 15 > 15 else startY + 15 cv2.putText(frame, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, COLORS[idx], 2) cv2.imshow("Frame", frame) key = cv2.waitKey(1)& 0xFF if key ==ord("q"): break fps.stop()print("[INFO] elapsed time :{:.2f}".format(fps.elapsed()))print("[INFO] approx. FPS :{:.2f}".format(fps.fps())) cv2.destroyAllWindows() #vs.stop()
上面的实现需要用到两个文件,是caffe实现好的模型,我直接上传(文件名为MobileNetSSD_deploy.caffemodel和MobileNetSSD_deploy.prototxt,上google能够下载到)。