文档章节

OpenCV单kinect多帧静止场景的深度图像去噪

moki_oschina
 moki_oschina
发布于 2016/04/08 23:50
字数 1067
阅读 94
收藏 0
#include<cv.h>
#include<highgui.h>
#include<iostream>
using namespace std;
#ifndef _DENOISE
#define _DENOISE
const int nFrames = 9;   // number of consecutive frames
const int width = 640;   // frame width
const int height = 480;  // frame height
class kinectDenoising
{
private:                       
 IplImage* denoisedImage;
 IplImage* frameSet[nFrames];
 unsigned int numOfFrames;
 CvRect imageROI;
public:
 kinectDenoising();
 ~kinectDenoising();
 void addFrame(IplImage* img); 
 void setImageROI(bool isUpdate = true);
 void medianFiltering(); 
 void nearestFiltering();
 void updateFrameSet(IplImage* img);
 void showDenoiedImage(const char* window);
 void showCurrentImage(const char* window);
};
void insertSort(unsigned short* data,int& len,unsigned short newData);
#endif

这是定义的头文件,装模作样的写了一个类,在构造函数里面,除了对denoisedImage分配内存之外其他都置0,析构函数需要释放denoisedImage和frameSet数组的内存。numOfFrames本来设计为frameSet中的图像的帧数,结果由于偷懒就用了一个定长的数组。

void kinectDenoising::setImageROI(bool isUpdate)
{
 if(!isUpdate) 
 {
  imageROI = cvRect(22,44,591,434);
 }
 else
 {
  IplImage* image8u = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
  IplImage* bitImage = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
  // cvThreshold can only handle images of 8UC1 or 32FC1
  cvConvertScale(frameSet[0],image8u,255.0/4096.0);
  cvThreshold(image8u,bitImage,0,1,CV_THRESH_BINARY);
        // the two mats rowReduced and colReduced have to be CV_32SC1 type
     // for function cvReduce() seems not to suitable for 16U type and 
     // 8U type doesn't have enough room for the result.
     CvMat* rowReduced = cvCreateMat(1,bitImage->width,CV_32FC1);
     // bitImage->width represents number of cols, while bitImage->height stands for rows
     CvMat* colReduced = cvCreateMat(bitImage->height,1,CV_32FC1);
     cvReduce(bitImage,rowReduced,0,CV_REDUCE_SUM);
     cvReduce(bitImage,colReduced,1,CV_REDUCE_SUM);
  // compute imageROI.x
     for(int i=0;i<rowReduced->cols;i++)
     {
   float temp = CV_MAT_ELEM(*rowReduced,float,0,i);
      if(temp>bitImage->height/3)
      {
    imageROI.x = i;
       break;
      }
     }
  // computer imageROI.width
     for(int i=rowReduced->cols;i>0;i--)
     {
   float temp = CV_MAT_ELEM(*rowReduced,float,0,i-1);
   if(temp>bitImage->height/3)
      {
    imageROI.width = i-imageROI.x;
        break;
   }
        }
  // compute imageROI.y
     for(int i=0;i<colReduced->rows;i++)
     {
      float temp = CV_MAT_ELEM(*colReduced,float,i,0);
      if(temp>bitImage->height/3)
      {
       imageROI.y = i;
       break;
      }
     }
  // compute imageROI.height
     for(int i=colReduced->rows;i>0;i--)
     {
      float temp = CV_MAT_ELEM(*colReduced,float,i-1,0);
      if(temp>bitImage->height/3)
      {
       imageROI.height = i-imageROI.y;
       break;
      }
     }
  // set memory free
  cvReleaseImage(&bitImage);
  cvReleaseImage(&image8u);
  cvReleaseMat(&rowReduced);
  cvReleaseMat(&colReduced);
 }
}

这是计算深度图像的滤波范围。由于深度图像和彩色图像的视点不一致,导致了将深度图像映射到彩色图像上时有效像素会缩小,典型的现象就是在深度图像的四周会出现黑色的区域。这个函数就是用来将四周的黑色框框去掉。用OpenCV的投影的方法。由于cvReduce()函数要进行累积和的计算,为了不使数据溢出,目标数组应该用32位的浮点型(此函数只支持8位unsigned char型和32位float型)。

void kinectDenoising::medianFiltering()
{
 // set result image zero
 cvSetZero(denoisedImage);
 unsigned short data[nFrames];
 int total;
 for(int i=imageROI.y;i<imageROI.y+imageROI.height;i++)
 {
  unsigned short* denoisedImageData = (unsigned short*)(denoisedImage->imageData+denoisedImage->widthStep*i);
  for(int j=imageROI.x;j<imageROI.x+imageROI.width;j++)
  {
   total = 0;
   for(int k=0;k<nFrames;k++)
   {
    insertSort(data,total,CV_IMAGE_ELEM(frameSet[k],unsigned short,i,j));
   }
   if(total != 0)
   {
    denoisedImageData[j] = data[total/2];
   }
  }
 }
}

中值滤波,统计有效点并排序,然后取中值。insertSort()函数用来将值按从小到大的顺序进行插入,鉴于篇幅的关系,就不贴出来了。

void kinectDenoising::nearestFiltering()
{
 CvPoint topLeft,downRight;
 IplImage* tempImage = cvCloneImage(denoisedImage);
 for(int i=imageROI.y;i<imageROI.y+imageROI.height;i++)
 {
  unsigned short* data = (unsigned short*)(denoisedImage->imageData+denoisedImage->widthStep*i);
  for(int j=imageROI.x;j<imageROI.x+imageROI.width;j++)
  {
   for(int k=1;data[j]==0;k++)
   {
    topLeft = cvPoint(j-k,i-k);    // j为行数 i为列数
    downRight = cvPoint(j+k,i+k);
    for(int m=topLeft.x;(m<=downRight.x) && (data[j]==0);m++)
    {
     if(m<0) continue;
     if(m>=width) break;
     if(topLeft.y>=0)
     {
      unsigned short temp = CV_IMAGE_ELEM(tempImage,unsigned short,topLeft.y,m);
         if(temp > 0)
         {
          data[j] = temp;
       break;
         }
     }
     if(downRight.y < height)
     {
      unsigned short temp = CV_IMAGE_ELEM(tempImage,unsigned short,downRight.y,m);
         if(temp > 0)
      {
          data[j] = temp;
       break;
         }
     }     
    }
    for(int m=topLeft.y;(m<downRight.y) && (data[j]==0);m++)
    {
     if(m<0) continue;
     if(m>=height) break;
     if(topLeft.x>0)
     {
      unsigned short temp = CV_IMAGE_ELEM(tempImage,unsigned short,m,topLeft.x);
      if(temp > 0)
         {
          data[j] = temp;
       break;
         }
     }
     if(downRight.x<width)
     {
      unsigned short temp = CV_IMAGE_ELEM(tempImage,unsigned short,m,downRight.x);
      if(temp > 0)
         {
          data[j] = temp;
       break;
         }
     }
    }
   }
  }
 }
 cvReleaseImage(&tempImage);
}


最后是中值滤波,从最内层开始,一层层往外扩,直到找到有效值为止。

运行结果



本文转载自:http://blog.csdn.net/augusdi/article/details/9014345

moki_oschina
粉丝 26
博文 202
码字总数 44864
作品 0
成都
程序员
私信 提问
ROS kinetic 机器视觉

ROS 中的图像数据 二维图像 显示图像类型 kinetic@vm:~$ roslaunch usbcam usbcam-test.launch kinetic@vm:~$ rostopic list /imageview/output /imageview/parameterdescriptions /imagevie......

youshijian99
2018/05/11
0
0
基于OpenCV和Python的文件操作——捕获摄像头的帧,在窗口显示图像,在窗口显示摄像头帧和视频文件的读/写

0 写在前面 这篇博客主要参考资料为《OpenCV 3计算机视觉Python语言实现》(Learning OpenCV 3 Computer Vison with Python)。 因为之前用Faster R-CNN做过一个红绿灯检测的小实践,但是Git...

learning_tortosie
2018/04/12
0
0
基于UE4+ OpenCV 的混合现实 (webCamera, mix-reality, blue screen matting)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/himilong/article/details/52829231 总体效果 类似混合现实,实现展示玩家玩的VR游戏的实况 基本思想 利用ope...

不负初心
2016/10/16
0
0
基于特征检测(SURF,SIFT方法)与特征匹配(Feature Matching)(FLANN方法)

def detectcornerpoints(self, keyframe, good_matches): 结果图: 将书本大小缩小到dstsize大小的1/2,同时还要移动1/4的距离: 书中运行起来的效果如下: import numpy as npfrom matplot...

liangjiubujiu
2018/05/23
0
0
千呼万唤始出来!OpenCV 4.0正式发布!

作者 | 周强(本文为作者独立观点,转载请联系作者) 来源 | 我爱计算机视觉 OpenCV 4.0 正式版来啦! 重回英特尔的 OpenCV 终于迎来一次大版本更新,增加了诸多新特性,快来一起看看吧~ 因...

AI科技大本营
2018/11/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊Elasticsearch的CircuitBreakerService

序 本文主要研究一下Elasticsearch的CircuitBreakerService CircuitBreakerService elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/indices/breaker/CircuitBreakerService.ja......

go4it
26分钟前
3
0
Spring系列教程六:AOP详细讲解

AOP 概述 什么是 AOP AOP:全称是 Aspect Oriented Programming 即:面向切面编程。 AOP技术是对OOP技术的一种延伸,AOP是面向纵向,OOP是面向横向。简单的说它就是把我们程序重复的代码抽取...

我叫小糖主
39分钟前
12
0
Qt编写数据可视化大屏界面电子看板9-曲线效果

一、前言 为了编写数据可视化大屏界面电子看板系统,为了能够兼容Qt4和嵌入式linux系统,尤其是那种主频很低的,但是老板又需要在这种硬件上(比如树莓派、香橙派、全志H3、imx6)展示这么华...

飞扬青云
今天
3
0
责任链模式

//这篇博客的博主真的不错,解析的都很清晰明了, https://blog.csdn.net/jason0539/article/details/45091639

南桥北木
今天
3
0
Flutter -------- dio网络请求

dio是Flutter中文网开源的一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等... 1.添加依赖# dependencies: dio: 2.1.x #...

切切歆语
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部