2012-10-02 41 views
6

Không chắc chắn có bất kỳ tên nào cho thuật toán này mà tôi hiện đang phát triển hay không. Vậy vấn đề của tôi là gì?Thuật toán để vẽ đường viền hoặc nét vẽ xung quanh bất kỳ hình ảnh trong suốt alpha

Tôi muốn vẽ nét vẽ xung quanh hình ảnh trong suốt alpha để phác họa nó. Kích thước của đột quỵ nên được người dùng xác định.

Tôi có một mảng được điền bằng 0 và số, xem xét từng mục của mảng dưới dạng ô giống như trong Game of Life. Một mục có 0 trống (pixel trong suốt), một mục có 1 là ô thế hệ đầu tiên (pixel không trong suốt), số lượng thế hệ được xác định bởi kích thước của hành trình xung quanh.

Ví dụ này mô tả một hình chữ nhật bao quanh bởi các giá trị alpha:

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

Sau đó, tôi muốn để cho những người phát triển một thế hệ mới bằng cách xung quanh mỗi 0 hệ Moore hàng xóm. Đó là thế hệ thứ hai (đột quỵ với 1px) - do đó mảng chăm sóc phát triển như sau:

0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 2 2 2 2 2 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 2 2 2 2 2 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 

thế hệ thứ 3 và thứ 4 (đột quỵ với 3px):

4 4 4 4 4 4 4 4 4 4 
4 3 3 3 3 3 3 3 3 4 
4 3 2 2 2 2 2 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 2 2 2 2 2 3 4 
4 3 3 3 3 3 3 3 3 4 
4 4 4 4 4 4 4 4 4 4 

Cho đến nay rất tốt. Tôi đang thực hiện tác vụ đơn giản này bằng đoạn mã sau:

for (int gen = 1; gen <= 4; gen++) 
{ 
    for (int x = 1; x < arrayWidth - 1; x++) 
    { 
     for (int y = 1; y < arrayHeight - 1; y++) 
     { 
      // See if this cell is in the current generation. 
      if (_generation[x + arrayWidth * y] == gen) 
      { 
       // Generate next generation. 
       for (int i = x - 1; i <= x + 1; i++) 
       { 
        for (int j = y - 1; j <= y + 1; j++) 
        { 
         if (_generation[i + arrayWidth * j] == 0 || _generation[i + arrayWidth * j] > gen) 
         { 
          _generation[i + arrayWidth * j] = gen + 1; 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Phương pháp này hoạt động hoàn hảo cho các hình dạng đơn giản như hình chữ nhật chẳng hạn. Nhưng làm thế nào tôi có thể làm điều này cho một hình elip? Ngay khi chúng tôi có loại một mẫu cầu thang trong các tế bào, tôi nhận được kết quả lộn xộn:

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

0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 2 2 2 2 2 2 0 0 0 0 
0 0 0 2 2 1 1 1 1 2 2 0 0 0 
0 0 2 2 1 1 1 1 1 1 2 2 0 0 
0 2 2 1 1 1 1 1 1 1 1 2 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 2 1 1 1 1 1 1 1 1 2 0 0 
0 0 2 2 1 1 1 1 1 1 2 2 0 0 
0 0 0 2 2 1 1 1 1 2 2 0 0 0 
0 0 0 0 2 2 2 2 2 2 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 

0 0 0 3 3 3 3 3 3 3 3 0 0 0 
0 0 3 3 2 2 2 2 2 2 3 3 0 0 
0 3 3 2 2 1 1 1 1 2 2 3 3 0 
3 3 2 2 1 1 1 1 1 1 2 2 3 3 
3 2 2 1 1 1 1 1 1 1 1 2 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 2 1 1 1 1 1 1 1 1 2 2 3 
3 3 2 2 1 1 1 1 1 1 2 2 3 3 
0 3 3 2 2 1 1 1 1 2 2 3 3 0 
0 0 3 3 2 2 2 2 2 2 3 3 0 0 
0 0 0 3 3 3 3 3 3 3 3 0 0 0 

Khi áp dụng thuật toán này để một hình elip, đường viền trông kinda lạ vì vấn đề này (bên trái: Kết quả thuật toán , phải: kết quả yêu cầu):

vấn đề ở đây là tôi không muốn có những 2 2 và 3 3 khối trùng lặp xảy ra mỗi khi tôi có điều này "cầu thang" mẫu:

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

Tôi muốn các tính toán thế hệ thứ 2 và thứ 3 trên trông như thế này:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 2 2 2 2 0 0 0 0 0 
0 0 0 0 2 1 1 1 1 2 0 0 0 0 
0 0 0 2 1 1 1 1 1 1 2 0 0 0 
0 0 2 1 1 1 1 1 1 1 1 2 0 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 0 2 1 1 1 1 1 1 1 1 2 0 0 
0 0 0 2 1 1 1 1 1 1 2 0 0 0 
0 0 0 0 2 1 1 1 1 2 0 0 0 0 
0 0 0 0 0 2 2 2 2 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 

0 0 0 0 0 3 3 3 3 0 0 0 0 0 
0 0 0 0 3 2 2 2 2 2 3 0 0 0 
0 0 0 3 2 1 1 1 1 2 3 0 0 0 
0 0 3 2 1 1 1 1 1 1 2 3 0 0 
0 3 2 1 1 1 1 1 1 1 1 2 3 0 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
0 3 2 1 1 1 1 1 1 1 1 2 3 0 
0 0 3 2 1 1 1 1 1 1 2 3 0 0 
0 0 0 3 2 1 1 1 1 2 3 0 0 0 
0 0 0 3 2 2 2 2 2 2 3 0 0 0 
0 0 0 0 3 3 3 3 3 3 0 0 0 0 

Tôi đã thử nhiều phương pháp để lọc ra những khối tế bào trùng lặp, nhưng tôi không thể tìm thấy một giải pháp dễ dàng và chung chung để giải quyết vấn đề.

Bất kỳ ý tưởng nào về cách lấy nét/đường viền như tôi nhận được từ Photoshop hoặc Paint.NET?

Cảm ơn!

Cheers P

+2

Tôi nghĩ rằng bạn có thể đạt được tiến bộ bởi 'dilation' hình thái với một 'cơ cấu element' thích hợp. Tôi không có thời gian để giải thích chi tiết, trong khi bạn chờ đợi một câu trả lời, hãy bắt đầu đọc tại http://en.wikipedia.org/wiki/Mathematical_morphology –

+1

Câu hỏi của bạn phải là một ví dụ cho mọi người - "Cách yêu cầu tốt câu hỏi " –

Trả lời

5

Tên riêng là dilation, hãy kiểm tra các hoạt động hình thái. Bạn nên thử giãn với phần tử vòng tròn, điều này sẽ cho bạn kết quả được yêu cầu.

Dưới đây là một mã Matlab cho thấy làm thế nào nó được thực hiện:

im = imcircle(70); 
im = padarray(im,[20,20]); 
figure;imshow(im); 
im2 = imdilate(im,strel('disk',8)); 
figure;imshow(im2); 

enter image description here

+2

Đây chính xác là những gì tôi đang tìm kiếm! Cảm ơn! Biết tên của thuật toán này giúp nghiên cứu dễ dàng hơn nhiều ...;) Một số liên kết rất hữu ích: http://homepages.inf.ed.ac.uk/rbf/HIPR2/dilate.htm Ngoài ra tham chiếu Matlab để chọn một hạt nhân thích hợp: http://www.mathworks.de/de/help/images/ref/strel.html – barnacleboy

+1

Khái niệm này đã giúp tôi giảm 160 dòng, tập lệnh phức tạp xuống ~ 20 dòng dễ đọc. Google đưa tôi đến trang tuyệt vời này: https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html – itnAAnti

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