前景的分割从背景

时间:2016-03-15 07:27:29

标签: c++ opencv image-segmentation

我目前正在开发一个使用 Lacatan Banana 的项目,我想知道如何进一步将前景与背景分开:

我已经使用侵蚀,扩张和阈值处理得到了它的分段图像。问题是它仍然没有被正确分割。

这是我的代码:

    cv::Mat imggray, imgthresh, fg, bgt, bg;
    cv::cvtColor(src, imggray, CV_BGR2GRAY); //Grayscaling the image from RGB color space
    cv::threshold(imggray, imgthresh, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU); //Create an inverted binary image from the grayscaled image
    cv::erode(imgthresh, fg, cv::Mat(), cv::Point(-1, -1), 1); //erosion of the binary image and setting it as the foreground
    cv::dilate(imgthresh, bgt, cv::Mat(), cv::Point(-1, -1), 4); //dilation of the binary image to reduce the background region
    cv::threshold(bgt, bg, 1, 128, CV_THRESH_BINARY); //we get the background by setting the threshold to 1
    cv::Mat markers = cv::Mat::zeros(src.size(), CV_32SC1); //initializing the markers with a size same as the source image and setting its data type as 32-bit Single channel
    cv::add(fg, bg, markers); //setting the foreground and background as markers                                                                
    cv::Mat mask = cv::Mat::zeros(markers.size(), CV_8UC1);
    markers.convertTo(mask, CV_8UC1);    //converting the 32-bit single channel marker to a 8-bit single channel
    cv::Mat mthresh;
    cv::threshold(mask, mthresh, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); //threshold further the mask to reduce the noise
    // cv::erode(mthresh,mthresh,cv::Mat(), cv::Point(-1,-1),2);
    cv::Mat result;
    cv::bitwise_and(src, src, result, mthresh);  //use the mask to subtrack the banana from the background
    for (int x = 0; x < result.rows; x++) { //changing the black background to white
        for (int y = 0; y < result.cols; y++) {
            if (result.at<Vec3b>(x, y) == Vec3b(0, 0, 0)){
                result.at<Vec3b>(x, y)[0] = 255;
                result.at<Vec3b>(x, y)[1] = 255;
                result.at<Vec3b>(x, y)[2] = 255;
            }
        }
    }

这是我的结果:

4 个答案:

答案 0 :(得分:0)

由于背景接近灰色,请尝试使用Hue通道和饱和度通道而不是灰度图像 你可以轻松搞定。

cv::Mat hsv;
cv::cvtColor(src, hsv, CV_BGR2HSV);
std::vector<cv::Mat> channels;
cv::split(src, channels);

cv::Mat hue = channels[0];
cv::Mat saturation = channels[1];

// If you want to combine those channels, use this code.
cv::Mat hs = cv::Mat::zeros(src.size(), CV_8U);
for(int r=0; r<src.rows; r++) {
    for(int c=0; c<src.cols; c++) {
        int hp = h.at<uchar>(r,c);
        int sp = s.at<uchar>(r,c);
        hs.at<uchar>(r, c) = static_cast<uchar>((h+s)>>1);
    }
}

答案 1 :(得分:0)

adaptiveTatreshold()应该比水平切割阈值()更好,因为它不考虑绝对颜色水平,而是考虑被检查点周围的小区域中的颜色变化。

尝试用自适应替换阈值。

答案 2 :(得分:0)

使用礼帽而不仅仅是侵蚀/扩张。它会同时处理背景变化。

然后在你的情况下,一个简单的阈值应该足够好,以便有一个准确的分割。否则,你可以将它与分水岭结合起来。

(我会尽快分享一些图片)。

答案 3 :(得分:0)

谢谢你们,我试着应用你们的建议,并且能够提出这个

enter image description here

然而,你可以看到仍然有一些背景,任何想法如何&#34;清洁&#34;进一步,我尝试了进一步的阈值,但它仍然有位。我提出的代码是下面,我提前道歉,如果变量和编码风格有点混乱没有时间来正确排序它们。

#include <stdio.h>
#include <iostream>
#include <opencv2\core.hpp>
#include <opencv2\opencv.hpp>
#include <opencv2\highgui.hpp>

using namespace cv;
using namespace std;

Mat COLOR_MAX(Scalar(65, 255, 255));
Mat COLOR_MIN(Scalar(15, 45, 45));


int main(int argc, char** argv){

Mat   src,hsv_img,mask,gray_img,initial_thresh;
Mat   second_thresh,add_res,and_thresh,xor_thresh;
Mat   result_thresh,rr_thresh,final_thresh;
// Load source Image
src = imread("sample11.jpg");
imshow("Original Image", src);
cvtColor(src,hsv_img,CV_BGR2HSV);
imshow("HSV Image",hsv_img);

//imwrite("HSV Image.jpg", hsv_img);

inRange(hsv_img,COLOR_MIN,COLOR_MAX, mask);
imshow("Mask Image",mask);

cvtColor(src,gray_img,CV_BGR2GRAY);
adaptiveThreshold(gray_img, initial_thresh, 255,ADAPTIVE_THRESH_GAUSSIAN_C,CV_THRESH_BINARY_INV,257,2);
imshow("AdaptiveThresh Image", initial_thresh);

add(mask,initial_thresh,add_res);
erode(add_res, add_res, Mat(), Point(-1, -1), 1);
dilate(add_res, add_res, Mat(), Point(-1, -1), 5);
imshow("Bitwise Res",add_res);

threshold(gray_img,second_thresh,170,255,CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
imshow("TreshImge", second_thresh);

bitwise_and(add_res,second_thresh,and_thresh);
imshow("andthresh",and_thresh);

bitwise_xor(add_res, second_thresh, xor_thresh);
imshow("xorthresh",xor_thresh);

bitwise_or(and_thresh,xor_thresh,result_thresh);
imshow("Result image", result_thresh);

bitwise_and(add_res,result_thresh,final_thresh);
imshow("Final Thresh",final_thresh);
erode(final_thresh, final_thresh, Mat(), Point(-1,-1),5);

bitwise_and(src,src,rr_thresh,final_thresh);
imshow("Segmented Image", rr_thresh);
imwrite("Segmented Image.jpg", rr_thresh);

waitKey(0);
return 1;
}