opencv 如何能把从摄像头中抓取的两帐图片进行精确比较?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv 如何能把从摄像头中抓取的两帐图片进行精确比较?相关的知识,希望对你有一定的参考价值。

偶是用的opencv 中的IpIImage类型接受的摄像头抓取到的帧,然后, cvGet2D(图像地址,y,x)值赋给CvScalar变量,再从CvScalar变量的val[0]、val[1]、val[2]值进行比较,用的是松下摄像机WV-CP500L/G,黑白摄像机,先抓一幅开机拍摄的图像,然后,摄像机不动,人实时在摄像机前走动,不断抓取图像,与第一幅图进行元素的RGB值对比,可就不精确,请赐教?!

//////////////////////////////////////////////////////////////////////////图片比较,并根据判断为不相同象素点的坐标值,用数组记录为1

for (int i = 0;i < nature_load->height; i++)

for (int j = 0;j < nature_load->width;j++)

sorce = cvGet2D(nature_load,i,j);
dest = cvGet2D(bgr_frame,i,j);

if(abs(sorce.val[0] - dest.val[0]) > 0||abs(sorce.val[1] - dest.val[1])> 0||abs(sorce.val[2] - dest.val[2]) > 0 )


arr[i][j] = 1;
if (max_x < j)

max_x = j;

if (min_x > j)

min_x = j;





参考技术A 你直接用帧差法看看就知道了
这种方法不靠谱的,一个是摄像机的白平衡,一个是移动目标对光场的扰动追问

谢谢,我已经解决了,我设定了个阈值60.因为通过摄像头抓取的两张图片,精确比较一定是不相同的,因为光线和摄像机拍摄的原因。所以设定阈值为60可以很好搞定:abs(sorce.val[0] - dest.val[0]) > 60||abs(sorce.val[1] - dest.val[1])> 60||abs(sorce.val[2] - dest.val[2]) > 60,这样问题就很好解决了。谢谢!

追答

这种方法能解决你的问题就好,我担心的是如果人身上的颜色和背景相差不到你说的阈值,有可能分离不出来

带有网络摄像机的 OpenCV

【中文标题】带有网络摄像机的 OpenCV【英文标题】:OpenCV with Network Cameras 【发布时间】:2010-10-17 07:31:38 【问题描述】:

我在 Windows 下使用 openCV 1.1pre1。 我有一个网络摄像机,我需要从 openCV 抓取帧。该摄像机可以通过 RTSP 流式传输标准 mpeg4 流或通过 http 传输 mjpeg。 我看到很多线程都在谈论将 ffmpeg 与 openCV 一起使用,但我无法使其工作。

如何使用 openCV 从 IP 摄像机中抓取帧?

谢谢

安德烈亚

【问题讨论】:

也检查这个答案:***.com/q/6022423/1085483 【参考方案1】:

使用 ffmpeglib 连接流。

这些功能可能很有用。但是请查看文档

av_open_input_stream(...);
av_find_stream_info(...);
avcodec_find_decoder(...);
avcodec_open(...);
avcodec_alloc_frame(...);

你需要一点算法来获得一个完整的框架, 可以在这里找到

http://www.dranger.com/ffmpeg/tutorial01.html

获得一帧后,您可以将视频数据(如果需要,针对每个平面)复制到 IplImage 是一个 OpenCV 图像对象。

您可以使用类似...的方式创建 IplImage

IplImage *p_gray_image = cvCreateImage(size, IPL_DEPTH_8U, 1);

一旦有了 IplImage,就可以执行 OpenCV 库中可用的各种图像操作

【讨论】:

我在很多线程中看到 ffmpeg 已经包含在 openCV 中并在其中使用,对吗?也许我需要重新编译带有 ffgmpeg 支持的 openCV?在这种情况下,我怎么能在 Windows 下做到这一点?谢谢 我不知道这一点。但是,ffmpeg 是一个应用程序,而 ffmpeglib 是一个库。如果您不熟悉这些内容,请查看 dranger.com 教程。【参考方案2】:

OpenCV 可以在 FFMPEG 支持下编译。来自./configure --help

--with-ffmpeg     use ffmpeg libraries (see LICENSE) [automatic]

然后您可以使用 cvCreateFileCapture_FFMPEG 创建一个 CvCapture,例如相机的 MJPG 流的 URL。

我用它从 AXIS 相机中抓取帧:

CvCapture *capture = 
    cvCreateFileCapture_FFMPEG("http://axis-cam/mjpg/video.mjpg?resolution=640x480&req_fps=10&.mjpg");

【讨论】:

能否在windows下配置openCV支持ffmpeg? 显然 opencv 2.x 在所有平台上总是支持 ffmpeg。【参考方案3】:

我只是这样做:

CvCapture *capture = cvCreateFileCapture("rtsp://camera-address");

还要确保这个 dll 在运行时可用,否则 cvCreateFileCapture 将返回 NULL

opencv_ffmpeg200d.dll

相机也需要允许未经身份验证的访问,通常通过其网络界面设置。 MJPEG 格式可以通过 rtsp 工作,但 MPEG4 不能。

【讨论】:

库版本说他正在使用openCV 2.0 - 那是opencv_ffmpeg200d.dll中的200部分 我认为这是正确的答案。我正在使用 Windows,我必须将 opencv_ffmpeg300.dll 复制到我的项目文件夹中。要打开我正在使用的流VideoCapture cap("rtsp://abc:123@192.168.178.101/live0.264");【参考方案4】:
#include <stdio.h>
#include "opencv.hpp"


int main()

    CvCapture *camera=cvCaptureFromFile("http://username:pass@cam_address/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=30&.mjpg");
    if (camera==NULL)
        printf("camera is null\n");
    else
        printf("camera is not null");

    cvNamedWindow("img");
    while (cvWaitKey(10)!=atoi("q"))
        double t1=(double)cvGetTickCount();
        IplImage *img=cvQueryFrame(camera);
        double t2=(double)cvGetTickCount();
        printf("time: %gms  fps: %.2g\n",(t2-t1)/(cvGetTickFrequency()*1000.), 1000./((t2-t1)/(cvGetTickFrequency()*1000.)));
        cvShowImage("img",img);
    
    cvReleaseCapture(&camera);

【讨论】:

【参考方案5】:

我附上了用于抓取帧的 C++ 代码。它需要 OpenCV 2.0 或更高版本。该代码使用 cv::mat 结构,该结构优于旧的 IplImage 结构。

#include "cv.h"
#include "highgui.h"
#include <iostream>

int main(int, char**) 
    cv::VideoCapture vcap;
    cv::Mat image;

    const std::string videoStreamAddress = "rtsp://cam_address:554/live.sdp"; 
    /* it may be an address of an mjpeg stream, 
    e.g. "http://user:pass@cam_address:8081/cgi/mjpg/mjpg.cgi?.mjpg" */

    //open the video stream and make sure it's opened
    if(!vcap.open(videoStreamAddress)) 
        std::cout << "Error opening video stream or file" << std::endl;
        return -1;
    

    //Create output window for displaying frames. 
    //It's important to create this window outside of the `for` loop
    //Otherwise this window will be created automatically each time you call
    //`imshow(...)`, which is very inefficient. 
    cv::namedWindow("Output Window");

    for(;;) 
        if(!vcap.read(image)) 
            std::cout << "No frame" << std::endl;
            cv::waitKey();
        
        cv::imshow("Output Window", image);
        if(cv::waitKey(1) >= 0) break;
       

更新您可以从 H.264 RTSP 流中抓取帧。查找您的相机 API 以获取详细信息以获取 URL 命令。例如,对于 Axis 网络摄像机,URL 地址可能是:

// H.264 stream RTSP address, where 10.10.10.10 is an IP address 
// and 554 is the port number
rtsp://10.10.10.10:554/axis-media/media.amp

// if the camera is password protected
rtsp://username:password@10.10.10.10:554/axis-media/media.amp

【讨论】:

你知道这是否仅适用于 MJPEG 或也适用于 H.264 RTSP/UDP 流媒体? @Matthias 它也适用于 H.264 RTSP 流。我有 OpenCV 2.4.4 版,可以从带有 H.264 的相机流中抓取帧。 感谢您的快速答复。 我必须在 for 循环中添加一些代码 counter++;if (counter % 10 != 0) continue;,以便仅显示每 10 帧。这是因为帧的接收速度非常快,以至于 imshow(...) 将显示损坏/扭曲的图像。如果您只向 imshow(...) 提供每 10 帧,结果就可以了。如果 IP 摄像机以 30fps 提供 1080p,我只需要每 30 帧或 40 帧显示一次。 好人...非常感谢...您的代码是最好的方法,我在这个问题上浪费了 4 天时间,您的解决方案现在让我非常高兴。【参考方案6】:

rtsp 协议对我不起作用。 mjpeg 第一次尝试。我假设它内置在我的相机中(Dlink DCS 900)。

在这里找到的语法: http://answers.opencv.org/question/133/how-do-i-access-an-ip-camera/

我不需要编译支持 ffmpg 的 OpenCV。

【讨论】:

第一次尝试时我不明白 mjpeg 是如何工作的,你用帧做了什么来获得 mjpeg 输出?

以上是关于opencv 如何能把从摄像头中抓取的两帐图片进行精确比较?的主要内容,如果未能解决你的问题,请参考以下文章

python之OpenCv---抓取摄像头视频图像

在python3下使用OpenCV 抓取摄像头图像提取蓝色

如何使用ffmpeg库把从摄像头传回的bmp图像不断保存成视频?

OpenCV|图片与视频的相互转换(C++&Python)

c#把从摄像机发过来的数据流转换成图片用picturebox显示出来

在python3下使用OpenCV 抓取摄像头图像并实时显示3色直方图