• T31开发笔记: 移动侦测


    若该文为原创文章,转载请注明原文出处。

    最近在测试创安源IPC时发现摄像头的视频流有移动侦测功能 ,拆解后发现使用的是T31,刚好手头上有淘宝买50多点的T31摄像头,就自己现在了个简易DEMO测试一下。

    一、硬件和开发环境

    1、硬件:T31X+SC5235 

    2、开发环境: ubuntu16.04-64bit

    3、编译器:mips-gcc540-glibc222-32bit-r3.3.0.tar.gz

    注:板子和和WIFI模块是某淘上淘的,使用的是RTL8188,使用的是USB接口,uboot和内核是自己裁剪移植的,内核默认自带WIFI驱动,所以不用移植可以直接使用。

    二、移动侦测原理

    以前有使用过海思hi3516ev200的移动侦测功能,感觉原理差不多。

    运行的demo是sample-Encoder-h264-IVS-base-move.c

    根据DEMO,移动侦测使用的是子流640*360,以区域方式来检测是否有移动,有移动输出1,

    即把640*360分成45*80个8*8的区域

    由此知道了移动的大概位置。而我试验的目的是通过这些区域算坐标并画框显示在界面上。

    三、使用步骤

    IMP 通过IVS的通用接口API调用实例化的IMPIVSInterface将智能化分析算法嵌入到SDK中来分析SDK中的frame图像。

    IMPIVSInterface为通用算法接口,具体算法通过实现此接口并将其传给IMP IVS达到在SDK运行具体算法的目的。

    一个channel有且仅为单个算法示例的载体,必须将具体实现的算法接口传给具体的channel才能在SDK中运行算法。

    IMPIVSInterface 成员 param 为成员函数 init 的参数。

    IMP_IVS 会在传给成员函数 ProcessAsync 参数的 frame 时对其进行外部加锁, ProcessAsync 必须在使用完 frame 后调用 IMP_IVS_ReleaseData 释放 frame,以免死锁。

    除上述通过绑定在数据流中的 IMP IVS 实现算法调用之外,还提供一种非绑定的方式实现算法 调 用 , 即 获 取 framesouce channel 的 frame 图 像 , 直 接 调 用 IMPIVSInterface 的成员函数实现算法处理。

    大部分情况下,我们使用的都是不绑定的方式进行移动侦测算法的获取的。

    绑定模式的算法使用方法:

    非绑定模式调用IVS平台

    具体的API参考API手册。

    四、代码说明

    sample-Encoder-h264-IVS-base-move例程已经输出了参数,结构体如下:

    其他数据data表示意思个人不理解,没有变化为0,有变化不为0,有人知道望告知。

    输出总的数据是3600即80*45通过下面代码他数据重新整理成一个多维数组。

    把检测到的值不为0,就表示1方式的方式存在arary[45][80]的数组里。 

    接下来通过算法,自己出为1的区域,

    计算边界值

    这个函数的作用是求一个10x10数组中值为1的元素的最大和最小行和列坐标

    通过此算法,即可获取到对应的区域

    附完整的测试代码:

    1. #include <stdio.h>
    2. #include <limits.h> // For INT_MAX and INT_MIN
    3. #define ROWS 10
    4. #define COLS 10
    5. void findMinMaxCoordinates(int array[ROWS][COLS], int *minRow, int *minCol, int *maxRow, int *maxCol) {
    6. *minRow = INT_MAX;
    7. *minCol = INT_MAX;
    8. *maxRow = INT_MIN;
    9. *maxCol = INT_MIN;
    10. for (int i = 0; i < ROWS; ++i) {
    11. for (int j = 0; j < COLS; ++j) {
    12. if (array[i][j] == 1) {
    13. if (i < *minRow) *minRow = i;
    14. if (j < *minCol) *minCol = j;
    15. if (i > *maxRow) *maxRow = i;
    16. if (j > *maxCol) *maxCol = j;
    17. }
    18. }
    19. }
    20. }
    21. int main() {
    22. int array[ROWS][COLS] = {
    23. 0,0,0,0,0,0,0,0,0,0,
    24. 0,0,1,0,0,0,0,0,0,0,
    25. 0,0,0,0,0,0,0,0,0,0,
    26. 0,0,0,0,0,0,0,0,0,0,
    27. 0,0,0,0,0,0,0,0,0,0,
    28. 0,0,0,0,0,0,0,0,0,0,
    29. 0,0,0,0,0,0,0,0,0,0,
    30. 0,0,0,0,0,0,0,0,0,0,
    31. 0,0,0,0,0,0,0,1,0,0,
    32. 0,0,0,0,0,0,0,0,0,0,
    33. };
    34. int minRow, minCol, maxRow, maxCol;
    35. findMinMaxCoordinates(array, &minRow, &minCol, &maxRow, &maxCol);
    36. if (minRow != INT_MAX && minCol != INT_MAX) {
    37. printf("Minimum coordinates: Row = %d, Col = %d\n", minRow, minCol);
    38. printf("Maximum coordinates: Row = %d, Col = %d\n", maxRow, maxCol);
    39. printf("(%d, %d) (%d, %d)\n", minCol, minRow ,maxCol, maxRow);
    40. } else {
    41. printf("No elements with value 1 found in the array.\n");
    42. }
    43. return 0;
    44. }

    把获取的坐标存到p00和p01结构体内,

    p00.x = minCol*8*3;
    p00.y = minRow*8*3;
     
    p01.x = maxCol*8*3;
    p01.y = maxRow*8*3;

    说明乘于8是因为roi区域是8*8, 乘于3是因为我在主码流1920*1080上叠加了OSD画框显示功能 。

    所以坐标放大3倍 。

    OSD画框参考的是sample_OSD.c例程。在update_thread更新线程里添加了显示框的坐标点。

    五、测试结果

    输出感觉有点不灵敏,具体参数还有待调试。

    此方式是个人想到的一种方法,有其他方式望互相讨论。

    如有侵权,或需要完整代码,请及时联系博主。

  • 相关阅读:
    【数据结构与算法】二叉树的遍历和线索二叉树
    模拟电子技术(六)信号的运算与处理
    面试失败总结,这 577 道 LeetCode 题 Java 版答案你值得拥有
    Could not find artifact com.mysql:mysql-connector-j:pom:unknown
    环形单链表问题
    cmd 开放 8018端口 --chatGPT
    在 Android Studio 中为 C++ 设置 OpenCV(4.6.0)
    Go Web——Gin使用中间件
    网络安全协议—SSL
    SpringSecurity Oauth2实战 - 02 搭建资源服务器
  • 原文地址:https://blog.csdn.net/weixin_38807927/article/details/137968231