“利用可见光传输信息的软件”项目简介(二)

团队——天亮说晚安

视频解码模块

//生成遮罩
std::vector<cv::Mat> mask(8);
for(int i = 0; i < 8; i++) {
   mask[i] = ...
}

目前,项目读取编码的手段是将图像根据定位点将图像尺寸还原,用遮罩捕获目标区域,所以需要先初始化std::vector<mask>

std::vector<cv::Mat>video_pro;
for (int k = 0; k < frames ; k++) {
   //彩色转灰度
   cv::cvtColor(src, src, cv::COLOR_RGB2GRAY);

   //阈值
   int SRC_THRESH_LOW = this->THRESH;
   cv::threshold(src, src, SRC_THRESH_LOW, 255, cv::THRESH_BINARY);

   //Canny边缘检测
   cv::Mat src_gray = src;
   cv::Mat canny_output;
   cv::Canny(src_gray, canny_output, 200, 255);

   //轮廓提取
   std::vector<std::vector<cv::Point> > contours;
   std::vector<cv::Vec4i> hierarchy;
   cv::findContours(canny_output, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

   if(contours.size()<1)//若提取失败,跳过此帧
       continue;

   //提取最大矩形,即屏幕现实范围
   cv::Rect poly_rect_max=cv::boundingRect(contours[0]);
   for (int i = 1; i < contours.size(); i++) {
        if(poly_rect_max.area()<cv::boundingRect(contours[i]).area())
             poly_rect_max=cv::boundingRect(contours[i]);
   }

   //ROI坐标生成 tl=topleft,br=bottomright
   int tl_x =  poly_rect_max.tl().x;
   int br_x =  poly_rect_max.br().x;
   int tl_y =  poly_rect_max.tl().y;
   int br_y =  poly_rect_max.br().y;

   //ROI区域生成
   cv::Rect rect(tl_x, tl_y, br_x - tl_x, br_y - tl_y);
   cv::Mat srcRoi=cv::Mat::zeros(src.size(), CV_8UC1);
   srcRoi=src(rect);
   cv::resize(srcRoi, srcRoi, RSFRAME);

   //存入预降噪vector保存
   video_pro.push_back(srcRoi);
}

这一步是降噪得以实现的核心,通过电脑屏幕底色的白色,将目标区域初步的提取出来,降低外部的噪声。cv::cvtColor()cv::threshold()实现初步的噪声去除,cv::Canny()cv::findContours提取出ROI区域和相应的轮廓,将轮廓外的区域全部消除。此步本应该为可选项,但是该段逻辑在Release 1.0的版本本是被强制执行的,会出现用户很精准的没有录入噪声,却读取失败的情况,Beta 2.0版本中拟予以优化。

std::vector<cv::Mat> video_diff;
for(int i=1;i<video_pro.size();i++){
   //差值
   cv::Mat st=video_pro[i]-video_pro[i-1];

   //形态学开
   cv::Mat kernelsrc = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(23, 23), cv::Point(-1, -1));
   cv::morphologyEx(st, st, cv::MORPH_OPEN, kernelsrc);

  //存入差值vector

  video_diff.push_back(st);
}

使用帧差法有两个目的,第一个是进一步去除噪声。第二目的是捕获关键帧。这里的关键帧是指清晰成像的,带有信息的图像。实际帧之间做差时,有三种情况:

  • [i-1]帧为空白帧,[i]帧为关键帧(无论清晰与否,下同)——这时,由于减去白色的缘故,[i]帧信息全部丢失。
  • [i-1]帧为关键帧,[i]也为关键帧——做差后,[i]会删去大部分信息,留下一些无用的噪点。
  • [i-1]帧为关键帧,[i]空白帧——这时,空白帧[i]会因为剪掉了信息区域外的黑色而保留信息区域。

这个时候,理论上,第一种情况产生黑色空白帧直接被忽略,第二种情况在形态学开操作cv::morphologyEx()的处理下,退化为黑色空白帧,只有第三种情况产生的帧会被捕获。但在实际解算时,由于灰阶响应的缘故,阈值后的信息会出现不完整的情况。这种情况会直接导致程序不正常退出或者OpenCV断言错误,实际UI显示为卡66%的进度。
Relese 1.0版本中这个现象尤为严重,因此为Relese 2.0版本发布前的重中之重。

for(int i=0;i<video_diff.size();i++){
   //过滤低信息图片
   if(cv::countNonZero(video_diff[i])==0)
       continue;
   cv::Mat read=video_diff[i];
   //Canny边缘查找
   cv::Mat src_gray = read;
   cv::Mat canny_output;
   cv::Canny(src_gray, canny_output, 200, 255);

   //轮廓查找
   std::vector<std::vector<cv::Point> > contours;
   std::vector<cv::Vec4i> hierarchy;
   cv::findContours(canny_output, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
   if(contours.size()<=2)
       continue;
   //从轮廓生成最小矩形
   std::vector<cv::Rect>poly_rect(contours.size());
   for (int i = 0; i < contours.size(); i++) {
      poly_rect[i] = cv::boundingRect(contours[i]);
   }
   //矩形轮廓x坐标整理
   for (int i = poly_rect.size(); i > 0; i--) {
       for (int j = 0; j < i - 1; j++) {
           if (poly_rect[j].tl().x > poly_rect[j + 1].tl().x)
               swap(poly_rect[j], poly_rect[j + 1]);
       }
   }
   //矩形轮廓y坐标整理
   for (int i = 0; i + 1 < poly_rect.size(); i += 2) {
       if (poly_rect[i].tl().y > poly_rect[i + 1].tl().y)
            swap(poly_rect[i], poly_rect[i + 1]);
   }

   //ROI坐标生成 tl=topleft,br=bottomright
   int tl_x = poly_rect[0].tl().x;
   int br_x = poly_rect[poly_rect.size() - 1].br().x;
   int tl_y = poly_rect[0].tl().y;
   int br_y = poly_rect[poly_rect.size() - 1].br().y;
   if(tl_x&&br_x&&tl_y&&br_y==0)
       continue;

   //矩形轮廓重建
   cv::Mat rscrc = cv::Mat::zeros(canny_output.size(), CV_8UC1);
   for (int i = 0; i < poly_rect.size(); i++) {
       cv::rectangle(rscrc, poly_rect[i], WHITE, cv::FILLED);
   }

   //ROI区域生成
   cv::Rect rect(tl_x, tl_y, br_x - tl_x, br_y - tl_y);
   cv::Mat srcRoi=cv::Mat::zeros(rscrc.size(), CV_8UC1);
   srcRoi=rscrc(rect);
   cv::resize(srcRoi, srcRoi, RSFRAME);

   //解码
   char c=0;
   for (int i = 7; i >= 0; i--) {
       //缓存帧
       cv::Mat p = cv::Mat::zeros(RSFRAME, CV_8UC1);

       //添加遮罩
       p = srcRoi-mask[i];

       //译码
       if (cv::countNonZero(p) >500)
           c |= 0x01;
       if (i != 0)
           c <<= 1;
   }
}

最后解码阶段,相当于第一步的复现,没有新的内容,最后的循环实现了解码,相当于编码的逆过程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352