运动图像分割

    xiaoxiao2026-03-02  7

    原文地址:http://blog.csdn.net/u011630458/article/details/50506473

    简介

      最近在继续看《数字图像处理》,发现上面一个分割运动图像的案例,用简单的代码实现,并整理了出来。

    原理介绍

      该方式主要是用在监控上面,用来处理在监控画面中运动的物体。原理可以大致为比较同一位置拍摄的两张图片之间各个像素像素差,根据像素差 大小来判断是否该位置为移动物体:   具体公式如下:   书中的具体效果如下:   注意:该方式局限性比较大,被处理的拍摄图像最好是保持相对光照恒定和做了图像配准的。

    实现

    具体代码

    [cpp] view plain copy #include <opencv2/opencv.hpp>  #include <stdio.h>  #include "opencv2/video/background_segm.hpp"  #include "opencv2/core/core.hpp"  #include "opencv2/video/background_segm.hpp"  #include "opencv2/imgproc/imgproc_c.h"  #include "opencv2/highgui/highgui.hpp"  #include "opencv2/legacy/legacy.hpp"     using namespace cv;  using namespace std;     Mat src1, src2, src3;  Mat picMask1, picMask2, dst;  int width, height;  int curThreshold = 10;     int cutSport(void){      int i, j;      IplImage ipI1, ipI2, ipI3, ipImask1, ipImask2, ipIdst;      CvScalar s1, s2, s3;         picMask1 =  Mat(width, height, CV_8UC1, cv::Scalar(0,0,0));        picMask2 =  Mat(width, height, CV_8UC1, cv::Scalar(0,0,0));        dst =  Mat(width, height, CV_8UC1, cv::Scalar(0,0,0));        ipI1 = src1;      ipI2 = src2;      ipI3 = src3;      ipIdst = dst;      ipImask1 = picMask1;      ipImask2 = picMask2;         for(i=1; i<width-1; i++){          for(j=1; j<height-1; j++){              s1 = cvGet2D(&ipI1, i, j);              s2 = cvGet2D(&ipI2, i, j);              s3 = cvGet2D(&ipI3, i, j);                 if(abs(s1.val[0] - s3.val[0]) > curThreshold){                  s1.val[0] = 255;                  cvSet2D(&ipImask1, i, j, s1);              }              if(abs(s2.val[0] - s3.val[0]) > curThreshold){                  s1.val[0] = 255;                  cvSet2D(&ipImask2, i, j, s1);              }          }      }      cvSegmentFGMask(&ipImask1);      cvSegmentFGMask(&ipImask2);         for(i=1; i<width-1; i++){          for(j=1; j<height-1; j++){                 s1 = cvGet2D(&ipImask1, i, j);              s3 = cvGet2D(&ipI1, i, j);              if(s1.val[0] == 255){                  s1.val[0] = s3.val[0];                  cvSet2D(&ipIdst, i, j, s1);              }                             s2 = cvGet2D(&ipImask2, i, j);              s3 = cvGet2D(&ipI2, i, j);              if(s2.val[0] == 255){                  s2.val[0] = s3.val[0];                  cvSet2D(&ipIdst, i, j, s2);              }                 if((s1.val[0] == 0) && (s2.val[0] == 0)){                  s1 = cvGet2D(&ipI3, i, j);                  cvSet2D(&ipIdst, i, j, s1);              }          }      }      return 0;  }     int main(int argc, char* argv[]){      if(argc < 4){          printf("Please input pic1 / pic2 / pic3!\n");          return -1;      }      src1 = imread(argv[1], 0);      src2 = imread(argv[2], 0);      src3 = imread(argv[3], 0);      height = src1.cols;      width = src1.rows;      cutSport();      imshow("src1", src1);      imshow("src2", src2);      imshow("src3", src3);      imshow("dst", dst);      imshow("mask1", picMask1);      imshow("mask2", picMask2);         waitKey(0);      return 0;  }  

    代码讲解

      1、准备三张图片,一张没有运动物体的模板图片,两张运动物体位置不一样的图片。 打开三张图片,并调用函数cutSport处理,最后将原图片,结果图片和两张掩码图片都显示出来。 [cpp] view plain copy src1 = imread(argv[1], 0);  src2 = imread(argv[2], 0);  src3 = imread(argv[3], 0);  height = src1.cols;  width = src1.rows;  cutSport();  imshow("src1", src1);  imshow("src2", src2);  imshow("src3", src3);  imshow("dst", dst);  imshow("mask1", picMask1);  imshow("mask2", picMask2);     2、在cutSport函数中,首先创建两张一样大小的掩码图片,像素全部设置为0。然后根据之前公式,分别对比两张运动图像和模板图像的差异,并将结果保存在两张掩码图片中。 [cpp] view plain copy picMask1 =  Mat(width, height, CV_8UC1, cv::Scalar(0,0,0));    picMask2 =  Mat(width, height, CV_8UC1, cv::Scalar(0,0,0));       for(i=1; i<width-1; i++){      for(j=1; j<height-1; j++){          s1 = cvGet2D(&ipI1, i, j);          s2 = cvGet2D(&ipI2, i, j);          s3 = cvGet2D(&ipI3, i, j);             if(abs(s1.val[0] - s3.val[0]) > curThreshold){              s1.val[0] = 255;              cvSet2D(&ipImask1, i, j, s1);          }          if(abs(s2.val[0] - s3.val[0]) > curThreshold){              s1.val[0] = 255;              cvSet2D(&ipImask2, i, j, s1);          }      }  }     3、对两个掩码结果做连通域分割处理。 [cpp] view plain copy cvSegmentFGMask(&ipImask1);  cvSegmentFGMask(&ipImask2);     4、利用处理后的掩码图像,分别将两张运动图像的运动物体,都复制到模板图片中去,形成结果图像。 [cpp] view plain copy for(i=1; i<width-1; i++){      for(j=1; j<height-1; j++){             s1 = cvGet2D(&ipImask1, i, j);          s3 = cvGet2D(&ipI1, i, j);          if(s1.val[0] == 255){              s1.val[0] = s3.val[0];              cvSet2D(&ipIdst, i, j, s1);          }                     s2 = cvGet2D(&ipImask2, i, j);          s3 = cvGet2D(&ipI2, i, j);          if(s2.val[0] == 255){              s2.val[0] = s3.val[0];              cvSet2D(&ipIdst, i, j, s2);          }             if((s1.val[0] == 0) && (s2.val[0] == 0)){              s1 = cvGet2D(&ipI3, i, j);              cvSet2D(&ipIdst, i, j, s1);          }      }  }  

    结果显示

      显示的结果如下:

    模板图像 运动图像1 运动图像2

    掩码图像1 掩码图像2 结果图像
    转载请注明原文地址: https://ju.6miu.com/read-1307540.html
    最新回复(0)