C代码实践——《Head first C》C语言实验室2

任务要求

入侵者检测器
计算机用摄像头持续监测周围环境,当检测到有物体在移动时就会把当前捕捉到的图像保存为文件。

完成过程

Step1.安装OpenCV

访问OpenCV官网下载适合操作系统的OpenCV,我起初下载的是最新版,但后来了解到最新版删除了不少旧版的C语言接口,就下回了2.x旧版本。

Step2.配置环境变量

将OpenCV的bin目录添加到系统环境变量中,具体操作如下

Step3.配置编译环境

创建工程并准备初步测试代码,在工程文件相应位置(我用vscode就在.vscode文件夹里)大致配置好tasks.json、c_cpp_properties.json,并进行测试
这是我第一次配置,我捯饬了老半天,一边问GPT一边自己瞎试,其实关键就是成功链接到opencv的相应库。

我的tasks.json配置如下:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: gcc.exe 生成活动文件",
            "command": "C:/Program Files/mingw64/bin/gcc.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe",
                "-ID:/opencv/opencv/build/include",
                "-LD:/opencv/opencv/build/x64/vc14/lib",
                "-lopencv_core2413",
                "-lopencv_imgproc2413",
                "-lopencv_highgui2413",
                "-lopencv_video2413"
            ],
            "options": {
                "cwd": "C:/Program Files/mingw64/bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "调试器生成的任务。"
        }
    ],
    "version": "2.0.0"
}

我的c_cpp_properties.json配置如下:

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**",
                "D:/opencv/opencv/build/include/"
            ],
            "defines": [],
            "windowsSdkVersion": "10.0.17763.0",
            "compilerPath": "C:/Program Files/mingw64/bin/gcc.exe",
            "cStandard": "c11",
            "cppStandard": "c++17",
            "intelliSenseMode": "${default}"
        }
    ],
    "version": 4
}

Step4.编写程序代码

按照任务要求与提示编写程序代码.现在有了GPT,方便很多,不懂的函数,直接让GPT手把手带你写,但这里我也出了不少几次错误,不过问GPT加自己“研究”(瞎捣鼓)也凑活写出来了。(具体代码见文尾)

Step5.测试运行调整

试运行程序并对程序代码进行调整。刚开始运行的时候,我人晃半天都检测不到,然后我就修改参数,改了几次之后也就差不多了。

反思、总结、收获

程序也凑合着能用了,但真要达到目的恐怕远远不够(比如这个程序只能记录最后一个可疑图像,而这个图像往往是thief离开的图像,很难看清thief)。
这个过程也是一波三折,一开始不知道配置环境变量,然后不会配置tasks.json、c_cpp_properties.json,后来程序也老是出错,折腾几天,有点头疼。不过这个过程也的的确确锻炼了自己做工程写程序的能力,积攒了相关的经验

最终程序代码

#include <opencv2/highgui/highgui_c.h>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv/cv.h>
#include <stdio.h>

int main()
{
    CvCapture *capture = cvCaptureFromCAM(0); // 从默认摄像头捕获视频
    if (!capture)
    {
        fprintf(stderr, "错误:无法打开摄像头\n");
        return -1;
    }

    IplImage *frame;
    IplImage *prev;
    IplImage *next;
    IplImage *prevGray;
    IplImage *nextGray;
    fprintf(stderr, "successly start!\n");

    while (1)
    {
        frame = cvQueryFrame(capture); // 从摄像头捕获一帧图像
        if (!frame)
            break;

        // 加载两帧图像
        prev = cvQueryFrame(capture);
        next = cvQueryFrame(capture);

        // 为灰度图像分配空间
        prevGray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
        nextGray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);

        // 将第一帧转换为灰度
        cvCvtColor(frame, prevGray, CV_BGR2GRAY);
        cvCvtColor(frame, nextGray, CV_BGR2GRAY);

        // 创建光流图像
        CvSize img_sz = cvGetSize(prevGray);
        CvMat *flow = cvCreateMat(img_sz.height, img_sz.width, CV_32FC2);

        // 计算光流
        cvCalcOpticalFlowFarneback(prevGray, nextGray, flow, 0.5, 5, 31, 3, 7, 1.5, 0);

        for (int y = 0; y < flow->rows; y++)
        {
            float *flow_ptr = (float *)(flow->data.ptr + flow->step * y);
            for (int x = 0; x < flow->cols; x++)
            {
                float x_flow = flow_ptr[x * 2];
                float y_flow = flow_ptr[x * 2 + 1];

                // 计算向量的大小(magnitude)
                float magnitude = sqrt(x_flow * x_flow + y_flow * y_flow);

                if (2 * x + 1 >= flow->cols)
                    break;

                // 检测显著运动
                if (magnitude > 0.5)
                {
                    cvSaveImage("thief.jpg", next, 0);
                    // 在这里处理显著运动的逻辑
                }
            }
        }

        // 释放图像和光流数据
        if (prevGray != NULL)
        {
            cvReleaseImage(&prevGray);
            prevGray = NULL; // 将指针设为NULL,防止野指针
        }

        if (nextGray != NULL)
        {
            cvReleaseImage(&nextGray);
            nextGray = NULL; // 同上
        }

        if (prev != NULL)
        {
            cvReleaseImage(&prevGray);
            prevGray = NULL; // 将指针设为NULL,防止野指针
        }

        if (next != NULL)
        {
            cvReleaseImage(&nextGray);
            nextGray = NULL; // 同上
        }

        if (flow != NULL)
        {
            cvReleaseMat(&flow);
            flow = NULL; // 同上
        }
    }

    cvReleaseCapture(&capture); // 释放IplImage资源

    return 0;
}
posted @ 2024-02-15 11:14  20231309  阅读(24)  评论(0编辑  收藏  举报