DeepStream之kafka开发

12 篇文章 22 订阅
2 篇文章 0 订阅

1. kafka的安装与配置

 不多赘述,参考敲代码的椰子@tsota两位博主的文章。

2. .sh文件编写

 开启kafka服务要开至少三个终端,我写了一个.sh文件进行批处理,且将这些放在一个终端的多个标签下。参考deepstream开发小结第3节

3. 发送数据改写

 本文继上篇文章deepstream开发小结进行了补充,重点介绍发送数据的改写。
 首先参考DeepStream配置文件 修改msg-conv-payload-typemsg-conv-msg2p-lib(好吧,我懒了,感觉看英文更直观准确,后面就没翻译了)
 其中msg-conv-payload-type=0表示发送最全的信息,即每个object一个信息。msg-conv-payload-type=1表示发送mini版信息,即一帧一个信息,包含所有objects。msg-conv-payload-type=256是自定义的信息,需要用户自己实现nvds_msg2p_*接口。参考官方论坛how to customize the json message sent to kafka server?
 其中mini类似下面格式(其他格式可以自己跑一下test4和test5,这里不贴图了)

{
  "version" : "4.0",
  "id" : 33,
  "#timestamp" : "2020-04-09T21:20:48.851Z",
  "sensorId" : "sensor1",
  "objects" : [
    "68|429|472|465|580|person",
    "12|462|463|516|598|person",
    "13|258|466|414|832|person",
    "69|57|457|195|785|person"
  ]
}

 本人是更改了/home/username/Downloads/deepstream_sdk_v4.0.2_x86_64/sources/libs/nvmsgconv目录下的nvmsgconv.cpp文件mini函数。源码见下:

static gchar *
generate_deepstream_message_minimal(NvDsMsg2pCtx *ctx, NvDsEvent *events, guint size)
{
    /*
  The JSON structure of the frame
  {
   "version": "4.0",
   "id": "frame-id",
   "@timestamp": "2018-04-11T04:59:59.828Z",
   "sensorId": "sensor-id",
   "objects": [
      ".......object-1 attributes...........",
      ".......object-2 attributes...........",
      ".......object-3 attributes..........."
    ]
  }
  */

    /*
  An example object with Vehicle object-type
  {
    "version": "4.0",
    "id": "frame-id",
    "@timestamp": "2018-04-11T04:59:59.828Z",
    "sensorId": "sensor-id",
    "objects": [
        "957|1834|150|1918|215|Vehicle|#|sedan|Bugatti|M|blue|CA 444|California|0.8",
        "..........."
    ]
  }
   */

    JsonNode *rootNode;
    JsonObject *jobject;
    JsonArray *jArray;
    guint i;
    stringstream ss;
    gchar *message = NULL;

    jArray = json_array_new();
    for (i = 0; i < size; i++)
    {
        ss.str("");
        ss.clear();

        NvDsEventMsgMeta *meta = events[i].metadata;
        ss << meta->trackingId << "|" << meta->bbox.left << "|" << meta->bbox.top
           << "|" << meta->bbox.left + meta->bbox.width << "|" << meta->bbox.top + meta->bbox.height
           << "|" << object_enum_to_str(meta->objType, meta->objectId);

        if (meta->extMsg && meta->extMsgSize)
        {
            // Attach secondary inference attributes.
            switch (meta->objType)
            {
            case NVDS_OBJECT_TYPE_VEHICLE:
            {
                NvDsVehicleObject *dsObj = (NvDsVehicleObject *)meta->extMsg;
                if (dsObj)
                {
                    ss << "|#|" << to_str(dsObj->type) << "|" << to_str(dsObj->make) << "|"
                       << to_str(dsObj->model) << "|" << to_str(dsObj->color) << "|" << to_str(dsObj->license)
                       << "|" << to_str(dsObj->region) << "|" << meta->confidence;
                }
            }
            break;
            case NVDS_OBJECT_TYPE_PERSON:
            {
                NvDsPersonObject *dsObj = (NvDsPersonObject *)meta->extMsg;
                if (dsObj)
                {
                    ss << "|#|" << to_str(dsObj->gender) << "|" << dsObj->age << "|"
                       << to_str(dsObj->hair) << "|" << to_str(dsObj->cap) << "|" << to_str(dsObj->apparel)
                       << "|" << meta->confidence;
                }
            }
            break;
            case NVDS_OBJECT_TYPE_FACE:
            {
                NvDsFaceObject *dsObj = (NvDsFaceObject *)meta->extMsg;
                if (dsObj)
                {
                    ss << "|#|" << to_str(dsObj->gender) << "|" << dsObj->age << "|"
                       << to_str(dsObj->hair) << "|" << to_str(dsObj->cap) << "|" << to_str(dsObj->glasses)
                       << "|" << to_str(dsObj->facialhair) << "|" << to_str(dsObj->name) << "|"
                       << "|" << to_str(dsObj->eyecolor) << "|" << meta->confidence;
                }
            }
            break;
            default:
                cout << "Object type (" << meta->objType << ") not implemented" << endl;
                break;
            }
        }

        json_array_add_string_element(jArray, ss.str().c_str());
    }

    // It is assumed that all events / objects are associated with same frame.
    // Therefore ts / sensorId / frameId of first object can be used.

    jobject = json_object_new();
    json_object_set_string_member(jobject, "version", "4.0");
    json_object_set_int_member(jobject, "id", events[0].metadata->frameId);
    json_object_set_string_member(jobject, "#timestamp", events[0].metadata->ts);
    if (events[0].metadata->sensorStr)
    {
        json_object_set_string_member(jobject, "sensorId", events[0].metadata->sensorStr);
    }
    else if (ctx->privData)
    {
        json_object_set_string_member(jobject, "sensorId",
                                      to_str((gchar *)sensor_id_to_str(ctx, events[0].metadata->sensorId)));
    }
    else
    {
        json_object_set_string_member(jobject, "sensorId", "0");
    }

    json_object_set_array_member(jobject, "objects", jArray);

    rootNode = json_node_new(JSON_NODE_OBJECT);
    json_node_set_object(rootNode, jobject);

    message = json_to_string(rootNode, TRUE);
    json_node_free(rootNode);
    json_object_unref(jobject);

    return message;
}

 利用类似json_object_set_array_member()函数(不一定是array,也可以是string或int)可以改写发送json数据的格式。代码理解比较简单,改写也很简单,就不赘述了。

4. 补充

 这里补充一些对于源码的理解。
 NvDsMsg2pCtx *ctx是配置文件, NvDsEvent *events是包含了NvDsEventMsgMeta的数组 ,guint size指一帧中object数量,几个object就在主文件中存几次eventmeta。

    typedef struct NvDsEventMsgMeta
    {
        /** type of event */
        NvDsEventType type;
        /** type of object */
        NvDsObjectType objType;
        /** bounding box of object */
        NvDsRect bbox;
        /** Geo-location of object */
        NvDsGeoLocation location;
        /** coordinate of object */
        NvDsCoordinate coordinate;
        /** signature of object */
        NvDsObjectSignature objSignature;
        /** class id of object */
        gint objClassId;
        /** id of sensor that generated the event */
        gint sensorId;
        /** id of analytics module that generated the event */
        gint moduleId;
        /** id of place related to the object */
        gint placeId;
        /** id of component that generated this event */
        gint componentId;
        /** video frame id of this event */
        gint frameId;
        /** confidence of inference */
        gdouble confidence;
        /** tracking id of object */
        gint trackingId;
        /** time stamp of generated event */
        gchar *ts;
        /** label of detected / inferred object */
        gchar *objectId;
        /** Identity string of sensor */
        gchar *sensorStr;
        /** other attributes associated with the object */
        gchar *otherAttrs;
        /** name of video file */
        gchar *videoPath;
        /**
   * To extend the event message meta data.
   * This can be used for custom values that can't be accommodated
   * in the existing fields OR if object(vehicle, person, face etc.) specific
   * values needs to be attached.
   */
        gpointer extMsg;
        /** size of custom object */
        guint extMsgSize;

    } NvDsEventMsgMeta;

 还有一个坑,就是char *必须用strdup()进行拷贝,如果是string转char *,不能直接str.c_str(),需要strdup(str.c_str())。否则你会发现要么乱码,要么就是设成常量或静态,字符串一帧中不会改变。

 如有其他问题可以评论,我再补充。总的来说kafka这里比较简单。

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值