2009-09-24 37 views
6

Tôi có hiểu biết lý thuyết về cách giãn nở trong hình ảnh nhị phân được thực hiện.thực hiện xói mòn, giãn nở trong C, C++

AFAIK, Nếu SE của tôi (cấu trúc phần tử) là này

0 1 
1 1. 

nơi. đại diện cho trung tâm, và hình ảnh của tôi (nhị phân là này)

0 0 0 0 0 
0 1 1 0 0 
0 1 0 0 0 
0 1 0 0 0 
0 0 0 0 0 

nên kết quả của sự giãn nở là

0 1 1 0 0 
1 1 1 0 0 
1 1 0 0 0 
1 1 0 0 0 
0 0 0 0 0 

tôi trên kết quả bằng cách thay đổi hình ảnh trong 0, +1 (up) và và - 1 (trái) hướng, theo SE, và lấy sự kết hợp của tất cả ba ca.

Bây giờ, tôi cần tìm ra cách thực hiện điều này trong C, C++. Tôi không chắc chắn làm thế nào để bắt đầu và làm thế nào để có sự kết hợp của bộ. Tôi nghĩ đến việc đại diện cho hình ảnh gốc, ba hình ảnh được chuyển đổi và hình ảnh cuối cùng thu được bằng cách kết hợp; tất cả đều sử dụng ma trận.

Có nơi nào tôi có thể nhận được một số giải pháp mẫu để bắt đầu hoặc bất kỳ ý tưởng nào để tiếp tục không?

Cảm ơn.

Trả lời

10

Có rất nhiều dự án triển khai mẫu ngoài kia .. Google là bạn của bạn :)

EDIT
Sau đây là một pseudo-code của quá trình này (rất tương tự như thực hiện một convolution trong 2D). Im chắc chắn có cách thông minh hơn để thực hiện:

// grayscale image, binary mask 
void morph(inImage, outImage, kernel, type) { 
// half size of the kernel, kernel size is n*n (easier if n is odd) 
sz = (kernel.n - 1)/2; 

for X in inImage.rows { 
    for Y in inImage.cols { 

    if (isOnBoundary(X,Y, inImage, sz)) { 
    // check if pixel (X,Y) for boundary cases and deal with it (copy pixel as is) 
    // must consider half size of the kernel 
    val = inImage(X,Y);  // quick fix 
    } 

    else { 
    list = []; 

    // get the neighborhood of this pixel (X,Y) 
    for I in kernel.n { 
    for J in kernel.n { 
     if (kernel(I,J) == 1) { 
     list.add(inImage(X+I-sz, Y+J-sz)); 
     } 
    } 
    } 

    if type == dilation { 
    // dilation: set to one if any 1 is present, zero otherwise 
    val = max(list); 
    } else if type == erosion { 
    // erosion: set to zero if any 0 is present, one otherwise 
    val = min(list); 
    } 
    } 

    // set output image pixel 
    outImage(X,Y) = val; 
    } 
} 
} 

Mã trên được dựa trên số tutorial này (hãy kiểm tra mã nguồn ở cuối trang).


EDIT2:

list.add (inImage (X + I-sz, Y + J-sz));

Ý tưởng là chúng tôi muốn chồng mặt nạ hạt nhân (kích thước nxn) vào giữa sz (một nửa kích thước mặt nạ) trên pixel ảnh hiện tại tại (X, Y), và sau đó chỉ nhận được cường độ của các pixel nơi giá trị mặt nạ là một (chúng tôi đang thêm chúng vào danh sách). Sau khi trích xuất tất cả các hàng xóm cho pixel đó, chúng tôi đặt pixel hình ảnh đầu ra thành tối đa danh sách (cường độ tối đa) cho giãn nở và min cho xói mòn (tất nhiên điều này chỉ hoạt động đối với hình ảnh thang độ xám và mặt nạ nhị phân)
Chỉ số cả X/Y và I/J trong câu lệnh trên được giả định bắt đầu từ 0. Nếu bạn thích, bạn luôn có thể viết lại các chỉ số của I/J bằng một nửa kích thước của mặt nạ (từ -sz đến + sz) với một thay đổi nhỏ (cách hướng dẫn mà tôi liên kết đang sử dụng) ...


Ví dụ:
Xem xét việc này mặt nạ 3x3 kernel đặt và tập trung vào điểm ảnh (X, Y), và xem cách chúng tôi đi qua các khu phố xung quanh nó:

-------------------- 
|  |  |  | sz = 1; 
--------------------  for (I=0 ; I<3 ; ++I) 
|  | (X,Y) |  |  for (J=0 ; J<3 ; ++J) 
--------------------   vect.push_back(inImage.getPixel(X+I-sz, Y+J-sz)); 
|  |  |  | 
-------------------- 
+0

Và trường hợp chúng ta có kích thước hạt nhân MxN = 1x3 trong đó M là chiều rộng và N là chiều cao thì sao? – svlada

+0

Mã chỉ có nghĩa là một phác thảo không phải là triển khai thực tế. Nhưng nếu bạn nhìn kỹ, bạn sẽ thấy tôi chỉ xử lý với N * N hạt nhân với N là số lẻ .. – Amro

+0

:) Có tôi thấy điều đó. Chỉ muốn nói rằng bạn có thể cải thiện mã của bạn chỉ bằng cách thêm kernelWidth kernelHeght và kiểm tra các ranh giới. – svlada

2

Có lẽ một cách tốt hơn để tìm kiếm đó là cách tạo ra một điểm ảnh đầu ra của sự giãn nở. Đối với pixel tương ứng trong hình ảnh, căn chỉnh phần tử cấu trúc sao cho gốc của phần tử cấu trúc ở điểm ảnh đó. Nếu có bất kỳ chồng chéo nào, hãy đặt pixel đầu ra giãn tại vị trí đó thành 1, nếu không đặt nó thành 0,

Vì vậy, điều này có thể được thực hiện bằng cách lặp lại từng pixel trong hình ảnh và kiểm tra xem cấu trúc có thay đổi đúng hay không phần tử trùng lặp với hình ảnh. Điều này có nghĩa là bạn có thể có 4 vòng lặp lồng nhau: x img, y img, x se, y se. Vì vậy, đối với mỗi pixel hình ảnh, bạn lặp qua các pixel của phần tử cấu trúc và xem liệu có bất kỳ trùng lặp nào hay không. Đây có thể không phải là thuật toán hiệu quả nhất, nhưng nó có lẽ là đơn giản nhất.

Ngoài ra, tôi nghĩ rằng ví dụ của bạn không chính xác. Sự giãn nở phụ thuộc vào nguồn gốc của yếu tố cấu trúc. Nếu nguồn gốc là ...

ở trên cùng bên trái số không: bạn cần phải thay đổi hình ảnh (-1, -1), (-1,0) và (0, -1) cho:

1 1 1 0 0 
1 1 0 0 0 
1 1 0 0 0 
1 0 0 0 0 
0 0 0 0 0 

ở phía dưới bên phải: bạn cần phải thay đổi hình ảnh (0,0), (1,0), và (0,1) cho:

0 0 0 0 0 
0 1 1 1 0 
0 1 1 0 0 
0 1 1 0 0 
0 1 0 0 0 

MATLAB sử dụng sàn ((kích thước (SE) 1)/2) là nguồn gốc của SE nên trong trường hợp này, nó sẽ sử dụng điểm ảnh trên cùng bên trái của SE. Bạn có thể xác minh điều này bằng cách sử dụng hàm imdilate MATLAB.

0
/* structure of the image variable 
* variable n stores the order of the square matrix */ 

typedef struct image{ 
     int mat[][]; 
     int n; 
     }image; 


/* function recieves image "to dilate" and returns "dilated"* 
* structuring element predefined: 
*    0 1 0 
*    1 1 1 
*    0 1 0 
*/ 

image* dilate(image* to_dilate) 
{ 
     int i,j; 
     int does_order_increase; 
     image* dilated; 

     dilated = (image*)malloc(sizeof(image)); 
     does_order_increase = 0; 

/* checking whether there are any 1's on d border*/  

     for(i = 0 ; i<to_dilate->n ; i++) 
     { 
      if((to_dilate->a[0][i] == 1)||(to_dilate->a[i][0] == 1)||(to_dilate->a[n-1][i] == 1)||(to_dilate->a[i][n-1] == 1)) 
      { 
       does_order_increase = 1; 
       break; 
      } 
     } 

/* size of dilated image initialized */  

     if(does_order_increase == 1) 
      dilated->n = to_dilate->n + 1; 
     else 
      dilated->n = to_dilate->n; 

/* dilating image by checking every element of to_dilate and filling dilated * 
* does_order_increase serves to cope with adjustments if dilated 's order increase */ 

     for(i = 0 ; i<to_dilate->n ; i++) 
     { 
      for(j = 0 ; j<to_dilate->n ; j++) 
      { 
       if(to_dilate->a[i][j] == 1) 
       { 
        dilated->a[i + does_order_increase][j + does_order_increase] = 1; 
        dilated->a[i + does_order_increase -1][j + does_order_increase ] = 1; 
        dilated->a[i + does_order_increase ][j + does_order_increase -1] = 1; 
        dilated->a[i + does_order_increase +1][j + does_order_increase ] = 1; 
        dilated->a[i + does_order_increase ][j + does_order_increase +1] = 1; 
       } 
      } 
     } 

/* dilated stores dilated binary image */ 

     return dilated; 
} 

/* end of dilation */ 
Các vấn đề liên quan