C++C++Visual Studio Code

Vscode Linux下opencv及多线程socket(3)

2019-05-26  本文已影响1人  applecai

继承我的上一篇文章Vscode mingw下opencv及多线程socket(2)--Apple的学习笔记中待完成任务。

一,本周做了变更(版本变更为0.3)

1. HMI图片显示添加ROI区域显示张数及叠加特质logo。
2. Server端切换到linux系统上。
3. recv存阻塞修改设计为select IO复用的异步形式,实现了断线也能重连的功能。
4. 对client测试code的重连函数中connect函数也使用非阻塞,加快重连速度。

注:client地址设置为192.168.1.111,server地址设置为192.168.1.110
工程共享路径(在code/03文件夹中): https://github.com/AppleCai/Display

二,后续更新版本说明:

之前的2.4/2.5算完成了,后续需要完成

2.6 重构HMI,分离为一个进程。
2.7 添加对图片的监视作用,添加弹窗报警及logDTC记录。(目的是使用进程间通信和共享内存)
2.8 添加守护进程。
2.9 进行性能测试,进行优化。

三,图片叠加设计说明

关于添加log及页数的方法:
每收到一帧则页数加1,将页数转为单个的字符串,自己制作0~9及logo的图片。将个十百千数字的位置及logo的位置固定后,进行opencv的ROI区域叠加即可。在原有函数中添加ROIhandler处理函数。

    void HMI::ROIhandler(ServerEx *serv)
    {
        /* Add logo ROI */
        cv::Mat mylogo = cv::imread("./pic/logo.png");
        cv::Mat imgROIlogo = serv->Img(cv::Rect(0, 0, mylogo.cols, mylogo.rows));
        mylogo.copyTo(imgROIlogo, mylogo);
    
        std::string suffix = ".png";
        /* int to string */
        std::string res = std::to_string(serv->page);
        /* stuff zero on the right*/
        while (res.size() < 4)
        {
          res = "0" + res;
        }
        /* setting number ROI get each item in string */
        cv::Mat numthousand = cv::imread("./pic/" + res.substr(0, 1) + suffix);
        cv::Mat imgROInumthousand = serv->Img(cv::Rect(mylogo.cols + 10, 0, numthousand.cols, numthousand.rows));
        numthousand.copyTo(imgROInumthousand, numthousand);
    
        cv::Mat numhundred = cv::imread("./pic/" + res.substr(1, 1) + suffix);
        cv::Mat imgROInumhundred = serv->Img(cv::Rect(mylogo.cols + 30, 0, numhundred.cols, numhundred.rows));
        numhundred.copyTo(imgROInumhundred, numhundred);
    
        cv::Mat numtens = cv::imread("./pic/" + res.substr(2, 1) + suffix);
        cv::Mat imgROInumtens = serv->Img(cv::Rect(mylogo.cols + 50, 0, numtens.cols, numtens.rows));
        numtens.copyTo(imgROInumtens, numtens);
    
        cv::Mat numunits = cv::imread("./pic/" + res.substr(3, 1) + suffix);
        cv::Mat imgROInumunits = serv->Img(cv::Rect(mylogo.cols + 70, 0, numunits.cols, numunits.rows));
        numunits.copyTo(imgROInumunits, numunits);
    }
    
    void HMI::DisplayFrame(ServerEx *serv)
    {
      if ((this->_showEn == TRUE) && (serv->revOK == TRUE))
      {
        ROIhandler(serv);
        /* show picture */
        cv::imshow("pic", serv->Img);
        cv::waitKey(1);
      }
    }

四,关于select模型的设计说明

一开始调试的时候,select过一段时间后就会一直返回0。明明已经设置了timeout时间为3s,这是为什么。通过wireshark监控没有发现超时,最后才知道每次select调用的时候timeout需要重新初始化为3s。
经过修改后,除非断线,否则不会返回0。因为一帧图片数据在1s内即可传输完毕。select函数的设计框架如下。

      this->myServerEx->select_zero();
      this->myServerEx->select_set();
      //重新select需要重新设置timeout值
      ret = this->myServerEx->myselect();
      if (ret == -1)
      {
          //出错处理
      }
      else if (ret == 0)
      {
          //超时处理
      }
      else
      {
          if (this->myServerEx->select_iset())
          {
              //正常执行
          }
      }
    void ServerEx::select_clr()
    {
      FD_CLR(this->getConnectfd(), &this->read_fds);
    }
    void ServerEx::select_zero()
    {
      FD_ZERO(&this->read_fds);
    }
    void ServerEx::select_set()
    {
      FD_SET(this->getConnectfd(), &this->read_fds);
    }
    int ServerEx::select_iset()
    {
      return (FD_ISSET(this->getConnectfd(), &this->read_fds));
    }
    int ServerEx::myselect()
    {
      this->tv.tv_sec=3;   //reset the timeout value
      this->tv.tv_usec=0;
      return (select(this->getConnectfd() + 1, &this->read_fds, NULL, NULL, &this->tv));
    }

五,运行效果图

实际效果.png
client.png
上一篇下一篇

猜你喜欢

热点阅读