批量图像自动分割 grabcut+阈值分割 opencv

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014679795/article/details/78696444

问题:白色等背景(幕布)下的批量图像,自动分割出前景物体,无须交互

环境: ubuntu 16.04 + opencv3 + openmp + cmake

**注意:具体分割效果可以自己调整腐蚀膨胀和grabcut中的阈值大小来优化。
本文章主要是用处理后的结果来重建物体,所以难以避免的是会保留一部分背景,以保证重建效果**

1.使用阈值分割,提取目标物体大概位置

//阈值分割,提取前景的大致轮廓
    threshold(gray,mask,0,255,THRESH_BINARY|CV_THRESH_OTSU);

2.通过膨胀腐蚀操作,构造出容纳物体的mask

    //膨胀,去掉噪点
    dilate(mask,mask, element1);
    if(debug) imshow("膨胀",mask);
    //腐蚀,得到整块的小车位置
    erode(mask, mask, element0);
    if(debug) imshow("腐蚀",mask);

3。构造出frabcut需要的mask图像,标记前后背景像素

    //构造grabcut的mask
    for(int i=0;i<mask.rows;i++)
    {
        for(int j=0;j<mask.cols;j++)
        {
            if(mask.at<uchar>(i,j)>100)
                mask.at<uchar>(i,j)=cv::GC_PR_BGD;//标记为可能的背景
            else
                mask.at<uchar>(i,j)=cv::GC_PR_FGD;//标记为可能的前景

        }
    }

4 调用opencv中的grabcut函数进行分割操作

 Mat bgModel,fgModel;
    grabCut(img,mask,Rect(0,0,img.cols,img.rows),bgModel,fgModel,1, cv::GC_INIT_WITH_MASK);

5.使用openmp多线程库,加速计算

#pragma omp parallel for
 for(int i=0;i<fileName.size();i++)
    {
        string filePath=basePath+fileName.at(i);
        cout<<filePath<<endl;
        Mat img=imread(filePath);
        if(img.empty())
        {
            cerr<<"读不到该图像!"<<endl;
            continue;
        }

        resize(img,img,Size(img.cols/3,img.rows/3));
        //imwrite(outputPath+fileName.at(i),img);

        //提取白布里面的部分
        img=getWhitePart(img);


        //imshow("original",img);

        Mat result=grabCutImage(img);
        //imshow("result", result);
        imwrite(outputPath+fileName.at(i),result);
        //waitKey(0);
    }

6.自动读取给定目录下的图片,输出到指定目录

vector<string> getFiles(string cate_dir)
{
    vector<string> files;//存放文件名

#ifdef WIN32
    _finddata_t file;
    long lf;
    //输入文件夹路径
    if ((lf=_findfirst(cate_dir.c_str(), &file)) == -1) {
        cout<<cate_dir<<" not found!!!"<<endl;
    } else {
        while(_findnext(lf, &file) == 0) {
            //输出文件名
            //cout<<file.name<<endl;
            if (strcmp(file.name, ".") == 0 || strcmp(file.name, "..") == 0)
                continue;
            files.push_back(file.name);
        }
    }
    _findclose(lf);
#endif

#ifdef linux
    DIR *dir;
    struct dirent *ptr;
    char base[1000];

    if ((dir=opendir(cate_dir.c_str())) == NULL)
        {
        perror("Open dir error...");
                exit(1);
        }

    while ((ptr=readdir(dir)) != NULL)
    {
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0|| ptr->d_name[0]=='.')    ///current dir OR parrent dir
                continue;
        else if(ptr->d_type == 8)    ///file
            //printf("d_name:%s/%s\n",basePath,ptr->d_name);
            files.push_back(ptr->d_name);
        else if(ptr->d_type == 10)    ///link file
            //printf("d_name:%s/%s\n",basePath,ptr->d_name);
            continue;
        else if(ptr->d_type == 4)    ///dir
        {
            files.push_back(ptr->d_name);
            /*
                memset(base,'\0',sizeof(base));
                strcpy(base,basePath);
                strcat(base,"/");
                strcat(base,ptr->d_nSame);
                readFileList(base);
            */
        }
    }
    closedir(dir);
#endif

    //排序,按从小到大排序
    sort(files.begin(), files.end());
    return files;
}

源图:

结果图:

源码下载地址:download.csdn.net/download/u014679795/10141966

猜你喜欢

转载自blog.csdn.net/u014679795/article/details/78696444