记一种彩色图像分割方法

由于运动物体的颜色不同(有些运动物体可能跟背景颜色比较接近),之前基于颜色的分割方法总是不尽如人意,虽然大部分情况下能够分割出运动物体,但有时存在分割不完整导致后续判断失误的情况。

今天尝试了一种方法,目前来看仿真效果还不错,除非出现一种极端情况,就是运动物体颜色(H、S、V三个分量跟背景完全相同),但这种情况出现的几率相对来说比较小,因此可以暂时忽略不计。

因为安全考虑,此处不贴原图,也不过多描述项目背景了,直接上代码看效果吧。

​
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;

int main()
{
    Mat srcImg, hsvSrcImg, dstImg, hsvDstImg;  
    srcImg = imread("7.bmp");    //参考图像
    dstImg = imread("8.bmp");    //当前图像
    cvtColor(srcImg, hsvSrcImg, COLOR_BGR2HSV);   //分别由BGR格式转换为HSV格式
    cvtColor(dstImg, hsvDstImg, COLOR_BGR2HSV);

    /* 分离参考图像HSV三通道 */
    vector<Mat> hsvChannels_src(3);
    split(hsvSrcImg, hsvChannels_src);

    /* 分离当前图像HSV三通道 */
    vector<Mat> hsvChannels_dst(3);
    split(hsvDstImg, hsvChannels_dst);


    /* 将参考图像与当前图像三个通道分别做绝对差值操作  */
    /* 当然,也可以用三通道对应像素的最大值,效果可以更好 */
    Mat H_diff;
    absdiff(hsvChannels_src[0], hsvChannels_dst[0], H_diff);
    Mat S_diff;
    absdiff(hsvChannels_src[1], hsvChannels_dst[1], S_diff);
    Mat V_diff;
    absdiff(hsvChannels_src[2], hsvChannels_dst[2], V_diff);


    /* 取绝对差值的平均值矩阵 */
    Mat hsv_diff = (H_diff + S_diff + V_diff) / 3;
    imshow("hsv_diff", hsv_diff);
    waitKey(0);
    imwrite("hsvDiff.bmp", hsv_diff);  //这句主要是为了此处贴图而把图像保存下来


    /* 由于运动物体不同时,上一步得到的hsv_diff有所差异,因此不便使用固定阈值 */
    /* 使用大津法(最大类间方差法)做自适应阈值分割,效果不错 */
    Mat binDiff;
    int th = threshold(hsv_diff,binDiff,0,255,CV_THRESH_OTSU);
    imshow("binary diff", binDiff);
    waitKey(0);
    printf("threshold = %d \n", th);
    imwrite("binary_diff.bmp", binDiff);


    /* 分割完成后,一些噪声点也会被当成前景分割出来,因此需要把这些零散的点腐蚀掉 */
    Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
    erode(binDiff, binDiff, element);
    imshow("eroded image", binDiff);
    waitKey(0);
    imwrite("eroded.bmp", binDiff);

    /* 腐蚀后原本连通的物体内部可能出现断开,因此在用膨胀算法将属于同一物体的像素连通起来 */
    Mat element_1 = getStructuringElement(MORPH_RECT, Size(15, 15)); 
    dilate(binDiff, binDiff, element_1);
    imshow("dilated image", binDiff);
    waitKey(0);
    imwrite("dilated.bmp", binDiff);

 }

三通道绝对差值的平均值矩阵:

对以上图像使用大津法做前景和背景分割,结果如下:

将二值化后的噪声点腐蚀掉:

通过膨胀,将属于同一个物体的像素点和像素块连接起来:

至此,已经较好地完成了画面上两只手臂和背景的分割,可以用此结果继续进行下面的操作步骤了。

这篇就简单写到这里。

发布了57 篇原创文章 · 获赞 58 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/DeliaPu/article/details/87719845