2011-01-08 22 views
12

Phương pháp thông thường tương phản 100% và một số điều chỉnh độ sáng để tinh chỉnh điểm cắt thường hoạt động khá tốt để làm sạch ảnh của các mạch con nhỏ hoặc phương trình để đăng trên E & R.SE, tuy nhiên đôi khi nó không hoàn toàn tuyệt vời, như với hình ảnh này:Tôi nên sử dụng các bước xử lý nào để làm sạch ảnh chụp các bản vẽ đường kẻ?

alt text

gì các phương pháp khác ngoài tương phản (hoặc thay thế) tôi có thể sử dụng để cung cấp cho tôi một đầu ra ổn định hơn?

Tôi đang mong đợi một câu trả lời khá chung chung, nhưng có lẽ tôi sẽ triển khai nó trong một tập lệnh (tôi chỉ có thể đổ tệp vào) bằng ImageMagick và/hoặc PIL (Python) vì vậy nếu bạn có bất kỳ điều gì cụ thể với chúng sẽ được chào đón.

Lý tưởng là hình ảnh nguồn tốt hơn sẽ đẹp, nhưng thỉnh thoảng tôi sử dụng hình ảnh này trên hình ảnh của người khác để thêm một số đánh bóng.

+1

Làm thế nào về màu sắc? Tôi không quen với xử lý hình ảnh, nhưng có vẻ như nếu bạn xóa mọi thứ trong một sự khác biệt nhất định của màu xanh, lưới sẽ bị xóa. – Mehrdad

Trả lời

15

Bước đầu tiên là cân bằng sự khác biệt chiếu sáng trong hình ảnh trong khi tính đến các vấn đề cân bằng trắng. Lý thuyết ở đây là phần sáng nhất của hình ảnh trong một khu vực giới hạn tượng trưng cho màu trắng. Bằng cách làm mờ hình ảnh trước, chúng tôi loại bỏ ảnh hưởng của nhiễu trong hình ảnh.

from PIL import Image 
from PIL import ImageFilter 
im = Image.open(r'c:\temp\temp.png') 
white = im.filter(ImageFilter.BLUR).filter(ImageFilter.MaxFilter(15)) 

alt text Bước tiếp theo là tạo ra một hình ảnh màu xám quy mô từ đầu vào RGB. Bằng cách chia tỷ lệ cho điểm trắng, chúng tôi sửa cho các vấn đề cân bằng trắng. Bằng cách lấy tối đa R, G, B, chúng tôi nhấn mạnh bất kỳ màu nào không phải là màu xám tinh khiết như các đường màu xanh của lưới. Dòng mã đầu tiên được trình bày ở đây là giả, để tạo ra một hình ảnh có kích thước và định dạng đúng.

grey = im.convert('L') 
width,height = im.size 
impix = im.load() 
whitepix = white.load() 
greypix = grey.load() 
for y in range(height): 
    for x in range(width): 
     greypix[x,y] = min(255, max(255 * impix[x,y][0]/whitepix[x,y][0], 255 * impix[x,y][2]/whitepix[x,y][3], 255 * impix[x,y][4]/whitepix[x,y][5])) 

Kết quả của các hoạt động này là một hình ảnh có giá trị chủ yếu là nhất quán và có thể chuyển đổi thành màu đen và trắng thông qua một ngưỡng đơn giản. alt text


Edit: Thật tuyệt khi nhìn thấy một cuộc thi nhỏ. nikie đã đề xuất một cách tiếp cận rất giống nhau, sử dụng phép trừ thay vì chia tỷ lệ để loại bỏ các biến thể ở cấp độ trắng.Phương pháp của tôi làm tăng độ tương phản ở các khu vực có ánh sáng yếu, và phương pháp của nikie không - phương pháp nào bạn thích sẽ phụ thuộc vào việc có thông tin trong các khu vực kém ánh sáng mà bạn muốn giữ lại hay không.

nỗ lực của tôi để tái tiếp cận này dẫn đến điều này:

for y in range(height): 
    for x in range(width): 
     greypix[x,y] = min(255, max(255 + impix[x,y][0] - whitepix[x,y][0], 255 + impix[x,y][7] - whitepix[x,y][8], 255 + impix[x,y][9] - whitepix[x,y][10])) 

alt text

Tôi đang làm việc trên sự kết hợp các kỹ thuật để cung cấp một kết quả thậm chí tốt hơn, nhưng nó không hoàn toàn sẵn sàng chưa.

+0

Chỉ cần một bình luận từ "cạnh tranh": Sự khác biệt chính giữa đề xuất của bạn và của tôi là bạn sử dụng một bộ lọc mờ (gaussian?) Theo sau là một bộ lọc tối đa (= dilation). Mỏ sử dụng một hình thái mở, mà lá gradients quy mô lớn hầu như không thay đổi. Vấn đề là, PIL không chứa các bộ lọc hình thái (hoặc tôi không tìm thấy chúng). – Niki

3

Làm thế nào về detecting edges? Điều đó sẽ nhận các bản vẽ đường thẳng.

Dưới đây là kết quả của Sobel phát hiện cạnh trên hình ảnh của bạn:

alt text

Nếu bạn sau đó ngưỡng hình ảnh (bằng cách sử dụng một ngưỡng theo kinh nghiệm quyết tâm hoặc Ohtsu method), bạn có thể dọn dẹp các hình ảnh sử dụng morphological operations (ví dụ như giãn nở và xói mòn). Điều đó sẽ giúp bạn thoát khỏi các dòng bị hỏng/đôi.

Như Lambert đã chỉ ra, bạn có thể xử lý trước hình ảnh bằng cách sử dụng kênh màu xanh lam để loại bỏ các đường lưới nếu bạn không muốn chúng trong kết quả của mình.

Bạn cũng sẽ nhận được kết quả tốt hơn nếu bạn ánh sáng trang đồng đều trước khi bạn hình ảnh nó (hoặc chỉ sử dụng máy quét) gây ra sau đó bạn không phải lo lắng về việc đẩy mạnh toàn cầu so với địa phương.

15

Một cách phổ biến để xóa ánh sáng nền khác nhau là tính "hình ảnh trắng" từ hình ảnh, bằng opening hình ảnh. Trong đoạn mã mẫu Octave này, tôi đã sử dụng kênh màu xanh của hình ảnh, bởi vì các dòng trong nền ít nổi bật nhất trong kênh này (EDITED: sử dụng phần tử cấu trúc tròn tạo ra ít tạo tác trực quan hơn đơn giản hộp):

src = imread('lines.png'); 
blue = src(:,:,3); 
mask = fspecial("disk",10); 
opened = imerode(imdilate(blue,mask),mask); 

Kết quả: opened

Sau đó trừ này từ hình ảnh nguồn:

background_subtracted = opened-blue; 

background_subtracted (Ngược lại phiên bản nâng cao)

Cuối cùng, tôi muốn chỉ binarize hình ảnh với một ngưỡng cố định:

binary = background_subtracted < 35; 

binary

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