2012-10-18 31 views
13

Tôi đang cố gắng để trừ nền từ hình ảnh sâu sắc thu được với kinect. Khi tôi học được những gì otsu thresholding là tôi nghĩ rằng nó có thể với nó. Chuyển đổi hình ảnh sâu sang màu xám tôi hy vọng có thể áp dụng ngưỡng otsu để binarize hình ảnh.Otsu thresholding cho hình ảnh chiều sâu

Tuy nhiên, tôi đã triển khai (đã cố gắng triển khai) điều này với OpenCV 2.3, điều đó vô ích. Hình ảnh đầu ra được binarized tuy nhiên, rất bất ngờ. Tôi đã làm liên tục thresholding (tức là in kết quả đến màn hình để phân tích cho mỗi khung hình) và thấy rằng đối với một số ngưỡng khung được tìm thấy là 160 và đôi khi nó được tìm thấy là 0. Tôi không thể hoàn toàn hiểu tại sao điều này xảy ra. Có thể là do số lượng lớn 0 trong hình ảnh độ sâu được trả về bởi kinect, tương ứng với các pixel không thể đo được. Có cách nào tôi có thể nói thuật toán bỏ qua các pixel có giá trị 0 không? Hoặc otsu thresholding là không tốt cho những gì tôi đang cố gắng để làm gì?

Dưới đây là một số kết quả đầu ra và phân đoạn của mã có liên quan. Bạn có thể nhận thấy rằng ảnh chụp màn hình thứ hai trông giống như nó có thể làm một số binarization tốt, tuy nhiên tôi muốn đạt được một sự khác biệt phân biệt giữa các điểm ảnh tương ứng với ghế trong cảnh và backgroung.

Cảm ơn.

  cv::Mat1s depthcv(depth->getHeight(), depth->getWidth()); 
      cv::Mat1b depthcv8(depth->getHeight(), depth->getWidth()); 
      cv::Mat1b depthcv8_th(depth->getHeight(), depth->getWidth()); 
      depthcv.data =(uchar*) depth->getDepthMetaData().Data(); 
      depthcv.convertTo(depthcv8,CV_8U,255/5000.f); 

      //apply otsu thresholding 
      cv::threshold(depthcv8, depthcv8_th, 128, 255, CV_THRESH_BINARY|CV_THRESH_OTSU); 
      std::ofstream output; 
      output.open("output.txt"); 
      //output << "M = "<< endl << " " << depthcv8 << endl << endl; 
      cv::imshow("lab",depthcv8_th); 
      cv::waitKey(1); 

Image 1 this second screenshot looks like it could do some good binarization

+2

Để thực hiện một ảnh chụp màn hình của cửa sổ duy nhất trong Ubuntu báo chí 'alt + prtsc'. – ArtemStorozhuk

+0

Tôi chỉ quen thuộc với Windows SDK chính thức, vì vậy không thể trả lời câu hỏi một cách trực tiếp. Tuy nhiên, nếu bạn có cài đặt Windows, có các ví dụ "màn hình xanh" trong ví dụ chính thức của Kinect cho Windows SDK Toolkit. Bạn có thể nhận được một số ý tưởng từ đó. Có lẽ... ? –

+0

xin vui lòng gửi hình ảnh đầu vào – nkint

Trả lời

13

Otsu có lẽ là đủ tốt cho những gì bạn đang cố gắng để làm, nhưng bạn cần phải để mặt nạ ra các giá trị số không trước khi tính toán ngưỡng tối ưu với các thuật toán Otsu, nếu không phân phối giá trị cường độ sẽ bị lệch thấp hơn giá trị bạn muốn.

OpenCV không cung cấp đối số mặt nạ cho hàm cv::threshold, vì vậy, bạn sẽ phải tự xóa các giá trị đó. Tôi khuyên bạn nên đặt tất cả các giá trị khác bằng ma trận 1 bởi N và gọi hàm cv::threshold với CV_THRESH_OTSU và lưu giá trị trả về (ngưỡng tối ưu ước tính) và sau đó chạy lại chức năng cv::threshold trên hình ảnh gốc chỉ có cờ CV_THRESH_BINARY và ngưỡng được tính.

Dưới đây là một thực thể:

// move zeros to the back of a temp array 
cv::Mat copyImg = origImg; 
uint8* ptr = copyImg.datastart; 
uint8* ptr_end = copyImg.dataend; 
while (ptr < ptr_end) { 
    if (*ptr == 0) { // swap if zero 
    uint8 tmp = *ptr_end; 
    *ptr_end = *ptr; 
    *ptr = tmp; 
    ptr_end--; // make array smaller 
    } else { 
    ptr++; 
    } 
} 

// make a new matrix with only valid data 
cv::Mat nz = cv::Mat(std::vector<uint8>(copyImg.datastart,ptr_end),true); 

// compute optimal Otsu threshold 
double thresh = cv::threshold(nz,nz,0,255,CV_THRESH_BINARY | CV_THRESH_OTSU); 

// apply threshold 
cv::threshold(origImg,origImg,thresh,255,CV_THRESH_BINARY_INV); 
Các vấn đề liên quan