机动车驾驶人考试系统中的实时视频合成系统

作者:shj 发布于:2019-1-24 14:54

去年在机动车驾驶人考试中,要求进行视频合成。并将合成的视频输入到NVR中进行保存。视频需要合成考试过程中的实时信息。整体的系统架构如图。

Image 205.jpg

整体的数据流向要求如数据流向图。针对这个要求,按照公安部的要求进行了设计以及实现。

Image 206.jpg

科目三的原型设计图。

Image 207.jpg

科目二原型设计图。

Image 202.jpg

整体实现后实时合成视频效果图。

目前本系统已经在多个考场合用。

测试使用电脑配置如表6-1,整体电脑配置中等。在科目二和科目三中将进行整体占用率测试。以确定本配置电脑可以同时进行多少路视频进行合成。整个测试系统均使用Ubuntu 16.06 64位服务器版系统。

6-1 测试电脑配置

配件名

配件型号及主要参数

CPU

Intel i5 7500

主板

微星 B250M MORTAR

内存

Team DDR4 2400 8G

硬盘

SEAGATE 1TB 7200

如图6-1,科目二考试过程视频合成系统在考试系统中正常运行。科目二考试过程视频合成过程中,经过实际长时间运行测试。同时合成15路视频时,CPU占用率为67%左右。而一般工作系统中需要保留30%的CPU资源以应对整个系统的突发调度和重载线程同时调度的情况。所以在针对科目二考试过程视频合成工作,我们认为一台i5的电脑基本可以满足同时15路视频的合成。

如果有本项目需求,或者视频系统定制需求可以与我们联系。联系方式为:shjmqqc@126.com

评论(0) 浏览(7032)

libstrophe简单介绍

作者:shj 发布于:2014-4-14 15:05

打算搞个XMPP的通信工具。俺搞就是个写C的,JAVA那么高大尚的俺不懂。只有找个C库方便移植的来用了。

初步选了下,选用libstrophe。但在网上找了半天没找到个中文的简单介绍。我就来写个算了。

先说下初始化:


	xmpp_ctx_t *ctx = NULL;
	xmpp_log_t *log;
	char jid[256]={"test1@jz"};
	/* take a jid and password on the command line */
	/*jid=username@host*/
	

	xmpp_initialize();

	log = xmpp_get_default_logger(XMPP_LEVEL_ERROR); /* pass NULL instead to silence output */

	ctx = xmpp_ctx_new(NULL, log);
	conn = xmpp_conn_new(ctx);

	/* setup authentication information */
	xmpp_conn_set_jid(conn, jid);
	xmpp_conn_set_pass(conn, "test1");
	/* initiate connection */
	xmpp_connect_client(conn, "shjpnn.com", 5222, conn_handler, ctx);


jid里需要注意,是用户名@域。XMPP服务器是要区分域的。如果不知道。。。就先看下这个在说。

ctx就当他是个标示吧。反正到处都在用。conn_handler是给libstrophe用的一个回调函数。在里面需要注册一些你关心的东西。

上面的完成之后需要的是xmpp_run(ctx);这里xmpp_run是一个阻塞的调用。之后收到消息都在 conn_handler里注册的回调。

先写这几句之后的空了写。



评论(18) 浏览(25635)

libstrophe编译

作者:shj 发布于:2014-2-19 11:01

使用vc2008编译libstrophe。
编译很简单,不过准备过程很有意思,随手记下:
1 下载libstrophe-master.zip
2 解压,看看各目录,expat是空的,再下载expat,解压,不需要编译,把.h和.c放到expat\lib下面。
3 然后先编译expat,顺利编译出 lib文件、
4 再编译libstrophe工程,会提示没有parser.c。看说明文档,libstrophe缺省用的是expat,可选用libxml2,进入 src下,看到有parser_libxml2.c和parser_expat.c,很明显,把parser_expat.c改名成parser.c就可 以了。编译通过。
5 再编译其他例子工程,提示没有va_copy。vc2008时好象没有兼容它,不过也没关系,这问题肯定很多人碰到过,果然随便一google,就有答案了, #define一下就行了。
6 全部编译通过,测试登录和发消息,api简洁明了,是目前见过最好用的xmpp库。当然gloox和qxmpp也都很好用,还有libjingle功能更强,各取所需。

标签: XMPP

评论(19) 浏览(19452)

unresolved external symbol ..........const gloox::GLOOX_VERSION

作者:shj 发布于:2014-2-11 9:41

error LNK2001: 无法解析的外部符号 "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const gloox::EmptyString" (?EmptyString@gloox@@3V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@B)
error LNK2001: 无法解析的外部符号 "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const gloox::GLOOX_VERSION" (?GLOOX_VERSION@gloox@@3V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@B)

 

解决方案:

在C++ console的Project  configuration properties\ c/c++ \Preprocesser\Preprcessor Definitions中加入GLOOX_IMPORTS 或 DLL_IMPORT 使extern 变量声明为 __declspec( dllimport );这样exe程序才认为这是个要从外部导入的变量。

评论(18) 浏览(19645)

ocr思考及测试

作者:shj 发布于:2014-2-9 11:57

外种外挂中ocr的应用必不可少,比如在EVE中的目标距离。如果没有目标距离根本无法进行下一步的操作。

现在只有先针ocr进行一些实验了。其实在自己动手做之前考虑过使用第三方免费开源库,测试了一下Tesseract-OCR。发现识别效果及速度并不能让人满意。主要是在识别的准确率上面。

现在先进行了一些偿试,第一步把图像抓取出来,这些之前已经做过了。然后是针对图像的处理,先试试2值化。效果直接上图。

根据效果可以看出,文字是进行过平滑的。直接使用2值化是不行的。下一步考虑使用色彩过滤后在进行2值化。然后在进行字符分割,在进行特征比对。。。。天工作量好大。

标签: EVE 外挂 OCR 识别

评论(42) 浏览(30541)

OpenCv 大图中找小图

作者:shj 发布于:2014-1-22 17:03

为了实现大图中找小图,之前是考虑使用OpenCv中的模板匹配。。。但发现速度太慢了。

前几天实在受不了,自己动手写了个特定情况下使用的。

把代码贴上来有兴趣的看了。


    clock_t starttime = clock();
    clock_t endtime = 0;
    int found = 0;
     
    IplImage *source1 = cvLoadImage("G:\\vctest\\OpenCv_Test\\图片\\030.png");
    IplImage *source2 = cvLoadImage("G:\\vctest\\OpenCv_Test\\图片\\0311.png");
    cvShowImage("source1",source1);
    cvShowImage("source2",source2);
     
    //FILE *fp = fopen("G:\\vctest\\OpenCv_Test\\图片\\030.tes","wb");
    //FILE *fp1 = fopen("G:\\vctest\\OpenCv_Test\\图片\\031.tes","wb");
    //fwrite(source1->imageData,source1->imageSize,1,fp);
    //fwrite(source2->imageData,source2->imageSize,1,fp1);
    //fclose(fp);
    //fclose(fp1);
     
     
     
    char *source1_data = source1->imageData;
    char *source2_data = source2->imageData;
     
    for(int h=0;h<source1->height - source2->height-1;h++)
    {
    for (int w=0;w<source1->width-source2->width-1;w++)
    {
    if (1 == contrast((unsigned char *)&source1_data[h*source1->widthStep+w*source1->nChannels],(unsigned char *)&source2_data[source2->width*source2->nChannels],source2->width*source2->nChannels,1))
    {
    found = 1;
    for (int ih = 1;ih < source2->height-1;ih++)
    {
    if (0 == contrast((unsigned char *)&source1_data[(h+ih)*source1->widthStep+w*source1->nChannels],(unsigned char *)&source2_data[ih*source2->widthStep+source2->width*source2->nChannels],source2->width*source2->nChannels,1))
    {
    found = 0;
    continue;
    }
    }
    if (found == 0)
    {
    break;
    }
    AfxOutputDebugString("find 1 line at:%d %d\n",w,h);
    endtime = clock();
    AfxOutputDebugString("time:%d\n",endtime-starttime);
    break;
    }
     
     
    }
    // AfxOutputDebugString("h::%d\n",h);
    }
     
     
     
    cvReleaseImage(&source1);
    cvReleaseImage(&source2);
    endtime = clock();
    AfxOutputDebugString("time:%d\n",endtime-starttime);

    int Cimage_contrast_01Dlg::contrast(unsigned char *source1,unsigned char *source2,int len,int a)
    {
    int i = 0;
    for (i=0;i<len-1;i++)
    {
    //if(source1[i] <= source2[i] - a || source1[i] >= source2[i] + a)
    if((abs(source1[i] - source2[i]) >= a))
    {
    return 0;
    }
    }
     
    return 1;
    }

评论(23) 浏览(34598)

不得不吐下炉石传说,更新太慢了。

作者:shj 发布于:2014-1-22 17:01

炉石传说在线更新太慢了。。。。

解决方法如下:



打开【IE浏览器】-【Internet属性】-【连接】

确保未勾选 【为LAN使用代理服务器】
若【自动检测设置】已勾选则取消!!!!!!!!!
若【自动检测设置】未勾选则勾选!!!!!!!!!


取消以后不用关闭更新程序,下载速度自动提升了。

评论(20) 浏览(26637)

记念开始,今天一定要写什么东东

作者:shj 发布于:2014-1-22 16:56

随便写个。。。eve market.先随便上张截图。完整程序下载地址market.zip









主要用了几个控件,截图上看看就明白了。

在程序中用了sqllite的数据库,用于所有物品的基础信息。

下面贴点代码。

    #pragma comment(lib,"sqlite3.lib") //连接了sqlite3的数据库。
     
    open_sql("new_eve.db");//初始化时打开了new_eve.db这个数据库。
    //打开和关闭数据库
    int Cmarket_V01App::open_sql(char *dbname)
    {
    int rc = 0;
    rc = sqlite3_open(dbname,&db);
    if (rc != SQLITE_OK)
    {
    CString debug_out = sqlite3_errmsg(db);
     
    sqlite3_close(db);
     
    return -1;
    }
     
    return 0;
    }
     
    void Cmarket_V01App::close_sql()
    {
    if (db != NULL)
    {
    sqlite3_close(db);
    }
    }
初始化时build了整个树结构代码如下:



    void Cmarket_V01App::build_tree(void *p)
    {
    Cmarket_V01Dlg *p_wnd = (Cmarket_V01Dlg *)p;
     
    char * errmsg = NULL;
    char **dbResult[5]; //是 char ** 类型,两个*号
    int nRow[5], nColumn[5];
    char sql[5][1024];
    int result,i,j,x,y,z;
    CString out;
     
     
    p_wnd->m_tree.GetCapture();
    HTREEITEM hTreeItemParent=NULL;
    HTREEITEM hTreeItemRoot=NULL;
    HTREEITEM hTreeChild[5] = {NULL};
     
    if (db == NULL)
    {
    return ;
    }
    hTreeItemRoot = p_wnd->m_tree.GetRootItem();
    hTreeItemParent=p_wnd->m_tree.InsertItem("吉他行情");
     
    result = sqlite3_get_table( db, "select distinct classify1 from eve_data", &dbResult[0], &nRow[0], &nColumn[0], &errmsg );
    if (result != SQLITE_OK)
    {
    return ;
    }
     
    out.Format("查到%d条记录\n", nRow[0] );
    OutputDebugString(out);
     
    //for( i = 0; i < nRow[0] ; i++ )
    //{
    // out.Format(" “第 %d 条记录\n", i );
    // OutputDebugString(out);
    // out.Format( "字段名:%s 字段值:%s\n", dbResult[0][0], dbResult[0][i+1] );
    // OutputDebugString(out);
    // out.Format( "-------\n" );
    // OutputDebugString(out);
    //}
    SetWindowPos(AfxGetMainWnd()->m_hWnd, HWND_TOPMOST, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOSIZE);
     
     
    for(i = 1;i < nRow[0];i++)
    {
    if (dbResult[0][i] == NULL)
    {
    continue;
    }
    out.Format("%s",dbResult[0][i]);
    hTreeChild[0] = p_wnd->m_tree.InsertItem(out,hTreeItemParent);
    sprintf(sql[0],"select distinct classify2 from eve_data where classify1 = '%s'",dbResult[0][i]);
    result = sqlite3_get_table( db, sql[0], &dbResult[1], &nRow[1], &nColumn[1], &errmsg );
    for( j = 1; j < nRow[1]+1 ; j++ )
    {
    if (dbResult[1][j] == NULL)
    {
    continue;
    }
    out.Format("查到%d条记录\n", nRow[1] );
    OutputDebugString(out);
    //out.Format(" “第 %d 条记录\n", j );
    //OutputDebugString(out);
    //out.Format( "字段名:%s 字段值:%s\n", dbResult[1][0], dbResult[1][j] );
    //OutputDebugString(out);
    //out.Format( "-------\n" );
    //OutputDebugString(out);
    out.Format("%s",dbResult[1][j]);
    hTreeChild[1] = p_wnd->m_tree.InsertItem(out,hTreeChild[0]);
    }
    sqlite3_free_table(dbResult[1]);
     
    }
    sqlite3_free_table(dbResult[0]);
     
     
    return ;
    }



因为数据库里面条数太多,整个EVE的数据库有5W多条。我们用的又是轻量级的数据库,在生成时查询所有数据并显示会导致程序启动需要初始化的时间过长。 这里我们启动时只加载前几个大项的数据,并没有加载所有数据。当选择具体的条目时在根据条目来进行添加。选择时的代码如下:

    void Cmarket_V01Dlg::OnNMClickTree1(NMHDR *pNMHDR, LRESULT *pResult)
    {
    // TODO: 在此添加控件通知处理程序代码
    CPoint pt;
    int i = 0;
     
    GetCursorPos(&pt);
     
    m_tree.ScreenToClient(&pt);
     
    CString classify_text[8]= {""};
    int classify_count = 0;
     
    UINT nFlag = 0;
    HTREEITEM hFather[8] = {NULL};
     
    HTREEITEM hChild = NULL;
     
    HTREEITEM hItem = m_tree.HitTest(pt, &nFlag);
     
    if( NULL != hItem )
     
    {
     
    m_tree.SelectItem(hItem);
     
    // CString strTemp=m_tree.GetItemText(hItem);
     
    DWORD nID=m_tree.GetItemData(hItem);
    if (nID != 0)
    {
    theApp.show_item((void *)this,nID);
     
    UpdateData(FALSE);
    *pResult = 0;
    return ;
     
    }
    hFather[6] = m_tree.GetParentItem(hItem);
    classify_text[0] = m_tree.GetItemText(hItem);
     
    // classify_text.Format("%d,%s",nID,strTemp);
    if (hFather[6] != NULL)
    {
    for (i = 5;i >= 0;i--)
    {
    hFather[i] = m_tree.GetParentItem(hFather[i+1]);
    if (hFather[i] == NULL)
    {
    break;
    }
     
    }
    classify_count = i;
    for (i;i <= 6 ;i++)
    {
    classify_text[6 - i + 1] = m_tree.GetItemText(hFather[i]);
    }
    }
     
    for (classify_count = 6 ;hFather[classify_count] != NULL;classify_count--)
    {
    ;
    }
    classify_count = 6 - classify_count;
     
    if (!m_tree.ItemHasChildren(hItem) )
    {
    printf("get");
    theApp.add_item((void *)this,classify_text,classify_count,hItem);
     
    }
     
     
    UpdateData(FALSE);
     
    }
    *pResult = 0;
    }

先写这些,数据库查询这些东东有需要的朋友留言我在贴吧。


评论(39) 浏览(32197)

开篇

作者:shj 发布于:2014-1-22 16:54

今天买了个阿里云服务器,花一下午的时间做域名的绑定。。。。结果晚上打电话才知道在国内的服务器没有备案之前是不能通过域名访问的。。。。。

评论(18) 浏览(23449)

Powered by emlog 蜀ICP备14001363号