2013-07-17 36 views
7

Tôi có hình ảnh (hình ảnh .jpg) và tôi muốn trích xuất nền từ hình ảnh gốc. Tôi đã googled rất nhiều nhưng chỉ tìm thấy hướng dẫn của giải nén hình ảnh tiền cảnh.Trích xuất ảnh nền bằng GrabCut

Tôi đã lấy mã từ một số khác stackoverflow question. Mã này làm việc tốt cho tôi, và tôi đã trích xuất thành công nền trước (theo yêu cầu của tôi). Bây giờ tôi muốn loại bỏ hoàn toàn tiền cảnh này khỏi ảnh gốc. Tôi muốn nó được một cái gì đó như thế này: -

Background = Original Image - Foreground

Các không gian trống rỗng có thể được lấp đầy với màu đen hoặc trắng. Làm thế nào tôi có thể đạt được điều này?

Tôi đã cố gắng sử dụng kỹ thuật này: -

Mat background = image2 - foreground; 

nhưng nó mang lại một hình ảnh màu đen hoàn toàn.

Code: -

#include <opencv2/opencv.hpp> 
#include <iostream> 

using namespace cv; 
using namespace std; 

int main() 
{ 
// Open another image 
Mat image; 
image= cv::imread("images/abc.jpg"); 

Mat image2 = image.clone(); 

// define bounding rectangle 
cv::Rect rectangle(40,90,image.cols-80,image.rows-170); 

cv::Mat result; // segmentation result (4 possible values) 
cv::Mat bgModel,fgModel; // the models (internally used) 

// GrabCut segmentation 
cv::grabCut(image, // input image 
      result, // segmentation result 
      rectangle,// rectangle containing foreground 
      bgModel,fgModel, // models 
      1,  // number of iterations 
      cv::GC_INIT_WITH_RECT); // use rectangle 
cout << "oks pa dito" <<endl; 
// Get the pixels marked as likely foreground 
cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ); 
// Generate output image 
cv::Mat foreground(image.size(),CV_8UC3,cv::Scalar(255,255,255)); 
//cv::Mat background(image.size(),CV_8UC3,cv::Scalar(255,255,255)); 
image.copyTo(foreground,result); // bg pixels not copied 

// draw rectangle on original image 
cv::rectangle(image, rectangle, cv::Scalar(255,255,255),1); 

imwrite("img_1.jpg",image); 

imwrite("Foreground.jpg",foreground); 
Mat background = image2 - foreground; 
imwrite("Background.jpg",background); 

return 0; 
} 

Lưu ý: Tôi là một người mới bắt đầu opencv và không có nhiều kiến ​​thức về nó ngay bây giờ. Tôi sẽ rất biết ơn bạn nếu bạn có thể đăng mã hoàn chỉnh (theo yêu cầu của tôi) hoặc chỉ đăng các dòng mã và cho tôi biết vị trí của các dòng mã này. Cảm ơn.

P.S. Đây là câu hỏi thứ hai của tôi tại StackOverflow.com. xin lỗi ... nếu không theo bất kỳ quy ước nào.

Trả lời

12

Thay vì sao chép tất cả các pixel được đặt nền trước, nó sẽ sao chép tất cả các điểm ảnh không có nền trước. Bạn có thể làm điều này bằng cách sử dụng ~, mà phủ nhận mặt nạ:

image.copyTo(background,~result); 
+0

Bạn đã đóng đinh nó. Cảm ơn :-) –

3

gì nếu bạn //Get the pixels marked as likely background:

// Get the pixels marked as likely background 
cv::compare(result,cv::GC_PR_BGD,result,cv::CMP_EQ); 

Sửa: Đoạn mã trên là mất tích pixel GC_BGD. Mặc dù một câu trả lời hiệu quả hơn đã được đưa ra, chúng ta hãy hoàn thành những gì chúng tôi bắt đầu:

// Get the pixels marked as background 
cv::compare(result,cv::GC_BGD,result_a,cv::CMP_EQ); 
// Get the pixels marked as likely background 
cv::compare(result,cv::GC_PR_BGD,result_b,cv::CMP_EQ); 
// Final results 
result=result_a+result_b; 
+0

Vâng, nó loại bỏ nền trước nhưng nó cũng sắp xếp các loại cây trồng hình ảnh vào hình chữ nhật tôi đã chỉ định. Cảm ơn bạn đã trả lời. –

+0

Vấn đề là, một số điểm ảnh được đánh dấu là 'GC_PR_BGD' (có thể là nền) và một số là' GC_BGD', có nghĩa là chúng chắc chắn là nền vì chúng đã được đưa làm đầu vào cho thuật toán. – sietschie

+0

Đúng. Chúng ta cần phải giữ cho cả hai có nghĩa là có thể thêm một dòng mã. – William

0

Chỉ cần một gợi ý nhỏ, @William's câu trả lời có thể được viết ngắn gọn hơn như:

result = result & 1; 

để có được mặt nạ nhị phân .

0

Có thể một ví dụ khác giúp, trong đó tôi giả định rằng phần giữa của hình ảnh chắc chắn là tiền cảnh. Vì vậy, hãy thử liên kết này. enter link description here

Các vấn đề liên quan