运动图像分割

来源:互联网 发布:手机电子狗软件那个准 编辑:程序博客网 时间:2024/05/30 04:44

简介

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

原理介绍

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

实现

具体代码

#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处理,最后将原图片,结果图片和两张掩码图片都显示出来。
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。然后根据之前公式,分别对比两张运动图像和模板图像的差异,并将结果保存在两张掩码图片中。
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、对两个掩码结果做连通域分割处理。
cvSegmentFGMask(&ipImask1);cvSegmentFGMask(&ipImask2);
  4、利用处理后的掩码图像,分别将两张运动图像的运动物体,都复制到模板图片中去,形成结果图像。
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                      结果图像
1 0
原创粉丝点击