2016-03-15 65 views
1

我目前正在对使用Lacatan香蕉一个项目,我想前景知道如何进一步前景从背景中分离:分割从背景

我已经使用侵蚀,扩张和阈值分割图像。问题在于它仍然没有被恰当地分割。

这是我的代码:

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; 
      } 
     } 
    } 

这是我的结果:

+0

这里是结果图像[链接](http://imgur.com/KG619PS)我还不很熟悉的分割如何工作的,请多多包涵:) –

+0

还我应该使用轮廓或任何其他技术呢? –

+0

这个图像看起来像是一个简单的例子。您是否尝试过一个简单的二进制阈值,并在结合Otsu过滤器之前使用阈值进行播放? – SpamBot

回答

0

如背景是接近灰色色,尝试使用代替灰度图像的色调信道和饱和度的信道。
你可以很容易地得到它们。

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); 
    } 
} 
+0

我可以问为什么在hsv?我问的很多人也说hsv色彩空间比较容易,但他们甚至没告诉我理由,伤心。 –

+0

@HarveyC https://en.wikipedia.org/wiki/HSL_and_HSV看看这里。总之,色调意味着“色彩方向”,饱和意味着“色彩强度”。香蕉多为黄色,因此色相在香蕉区大多相似。 –

0

adaptiveThreshold()应该工作不仅仅是水平切阈值()更好,因为它不考虑绝对的色彩层次,而是被检查在围绕该点的小区域颜色的变化。

尝试用自适应替换您的阈值。

0

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

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

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

0

谢谢你们,我尝试套用您的建议,并能想出这个

enter image description here

但是你可以看到仍存在的背景下位,任何想法如何“干净”这些进一步,我试图进一步thresholding,但它仍然有位。我想到的代码是在下面,我提前道歉,如果变量和编码风格有点混乱没有时间来正确排序它们。

#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; 
}