从MJPEG流中追踪OpenCV对象

1 投票
2 回答
3980 浏览
提问于 2025-04-18 13:54

我成功地用mjpeg-streamer从我的设备捕获了一个mjpeg流。下面的代码是我如何在OpenCV-python中获取这个流的:

import cv2
import numpy as np
import urllib

stream=urllib.urlopen('http://@192.168.7.2:8090/?action=stream/frame.mjpg')
bytes=''
while True:
    bytes+=stream.read(1024)
    a = bytes.find('\xff\xd8')
    b = bytes.find('\xff\xd9')
    if a!=-1 and b!=-1:
        jpg = bytes[a:b+2]
        bytes= bytes[b+2:]
        i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.CV_LOAD_IMAGE_COLOR)
        cv2.imshow('i',i)
        if cv2.waitKey(1) ==27:
            exit(0) 

我还有一段代码可以根据颜色范围追踪移动的物体。这个代码的视频源是直接从摄像头获取的,使用的是OpenCV的原生功能。以下是这段代码:

import cv2.cv as cv
import time
import sys

capture = CaptureFROMCAM(0)

while True:
img = cv.QueryFrame(capture)


cv.Smooth(img,img,cv.CV_BLUR,3)
hue_img = cv.CreateImage(cv.GetSize(img),8, 3)
cv.CvtColor(img,hue_img, cv.CV_BGR2HSV)

# Remove all the pixels that don't match
threshold_img = cv.CreateImage(cv.GetSize(hue_img), 8, 1)
cv.InRangeS(hue_img, (100,180,80), (225,160,80), threshold_img)

# Find all the areas of color out there
storage = cv.CreateMemStorage(0)
contour = cv.FindContours(threshold_img, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)

# Step through all the areas
points = []
while contour:
    # Get the info about this area
    rect = cv.BoundingRect(list(contour))
    contour = contour.h_next()
    # Check to make sure the area is big enough to be of concern
    size = (rect[2] * rect[3])
    if size > 25:
        pt1 = (rect[0], rect[1])
        pt2 = (rect[0] + rect[2], rect[1]+rect[3])
        # Add a rectangle to the initial image
        cv.Rectangle(img, pt1, pt2, (15,15,255))    

threshold_img = cv.CreateImage(cv.GetSize(hue_img),8,1)
cv.InRangeS(hue_img, (16,82,19), (30,255,255), threshold_img)

cv.ShowImage("Color Tracking", img)
cv.ShowImage("threshold", threshold_img)    

if cv.WaitKey(10) == 27:
    success, frame = videoCapture.read()
    while success:
        videoWriter.write(frame)
        success, frame = videoCapture.read()
    break

我的问题是:我该如何将这两个过程结合起来,以便我可以将第一个程序解码后的jpeg图像作为第二段代码中图像处理的输入?我尝试了各种组合,但还是没有成功。我一直收到这个错误:

cv.QueryFrame没有有效的参数'capture'

这让我知道它不喜欢我试图输入的jpeg格式。有没有人有什么建议?谢谢!!!

2 个回答

0

看第一段代码,当你执行 cv2.imshow('i',i) 时,摄像头拍到的画面会在一个窗口中显示出来。

在这个时候,你应该用第二段代码中的算法来处理这个图像,而不是直接显示它,这个算法是从 img = cv.QueryFrame(capture) 开始的。也就是说,你不需要下面这些代码了:

capture = CaptureFROMCAM(0)

while True:
img = cv.QueryFrame(capture)
1

连接这两种算法的关键点在于:

#infinite loop
#...stream reading operations
if a!=-1 and b!=-1:
    jpg = bytes[a:b+2]
    bytes= bytes[b+2:]
    img = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.CV_LOAD_IMAGE_COLOR)
    if cv2.waitKey(1) ==27:
        exit(0) 
else:
    continue
cv.Smooth(img,img,cv.CV_BLUR,3)
#... other tracker operations ...

imdecode函数是用来“从内存中的缓冲区读取图像”的。QueryFrame则是从视频捕捉设备读取数据,并返回一张图像。(它的意思是“抓取、解码并返回下一个视频帧。”)所以这两种方法都能给你一张图像对象,但来源不同(一个是相机,一个是缓冲区)。而图像正是你在追踪器中进一步处理所需要的东西!大多数OpenCV的方法都需要图像作为它们的基本数据格式。

整个流程大致是这样的:捕获帧/从图像文件或视频中加载图片->[图像]->对图像进行处理、计算、阈值、轮廓等操作 -> 显示结果或修改后的图像 -> 不断重复这个过程(永远这样 :-))。想了解更多信息,可以查看http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html

撰写回答