2015-10-19 13 views
10

Phương pháp nhanh nhất đáng tin cậy nhất để phát hiện một đường laser đỏ nằm ngang trong một hình ảnh bằng cách sử dụng Python là gì? Tôi đang nghiên cứu một dự án nhỏ liên quan đến quét laser 3D và tôi cần có khả năng phát hiện tia laser trong một hình ảnh để tính khoảng cách từ sự biến dạng của nó.Làm thế nào để phát hiện một đường laser trong một hình ảnh bằng cách sử dụng Python

Để bắt đầu, tôi có hai hình ảnh, một hình ảnh tham chiếu A được biết là không chứa đường laser, và hình ảnh B chắc chắn chứa đường laser, có thể bị méo. ví dụ.

Ảnh mẫu A:

enter image description here

Ảnh mẫu B:

enter image description here

Kể từ đây là những RGB, nhưng laser màu đỏ, tôi loại bỏ một số tiếng ồn bằng cách tách ra khỏi màu xanh và các kênh màu xanh lục sử dụng chức năng này:

from PIL import Image 
import numpy as np 

def only_red(im): 
    """ 
    Strips out everything except red. 
    """ 
    data = np.array(im) 
    red, green, blue, alpha = data.T 
    im2 = Image.fromarray(red.T) 
    return im2 

Đó được tôi những hình ảnh này:

enter image description here

enter image description here

Tiếp theo, tôi cố gắng và loại bỏ tiếng ồn hơn bằng cách lấy sự khác biệt của hai hình ảnh này sử dụng PIL.ImageChops.difference(). Lý tưởng nhất, sự tiếp xúc giữa hai hình ảnh sẽ giống hệt nhau, gây ra sự khác biệt không chứa gì ngoại trừ dòng laser. Thật không may, bởi vì laser thêm ánh sáng, độ phơi sáng và độ sáng tổng thể của mỗi ảnh là khác nhau đáng kể, dẫn đến sự khác biệt mà vẫn có tiếng ồn đáng kể. ví dụ.

enter image description here

bước cuối cùng của tôi là để thực hiện một "đoán tốt nhất" như là nơi dòng là. Vì tôi biết đường thẳng sẽ nằm ngang và đường laser nên là thứ sáng nhất trong hình ảnh, tôi quét từng cột và tìm hàng có pixel sáng nhất mà tôi cho là đường laser. Mã cho điều này là:

import os 
from PIL import Image, ImageOps 
import numpy as np 

x = Image.open('laser-diff.png', 'r') 
x = x.convert('L') 

out = Image.new("L", x.size, "black") 
pix = out.load() 

y = np.asarray(x.getdata(), dtype=np.float64).reshape((x.size[1], x.size[0])) 
print y.shape 
for col_i in xrange(y.shape[1]): 
    col_max = max([(y[row_i][col_i], row_i) for row_i in xrange(y.shape[0])]) 
    col_max_brightness, col_max_row = col_max 
    print col_i, col_max 
    pix[col_i, col_max_row] = 255 

out.save('laser-line.png') 

Tất cả tôi thực sự cần phải thực hiện tính toán khoảng cách của tôi là mảng col_max giá trị, nhưng laser-line.png giúp tôi hình dung sự thành công, và trông giống như:

enter image description here

Như bạn có thể thấy, ước tính là khá gần, nhưng nó vẫn có một số tiếng ồn, chủ yếu là ở phía bên trái của hình ảnh, nơi dòng laser được hấp thụ bởi một kết thúc màu đen mờ.

Tôi có thể làm gì để cải thiện độ chính xác và/hoặc tốc độ của mình? Tôi đang cố gắng để chạy điều này trên một nền tảng ARM như Raspberry Pi, vì vậy tôi lo lắng mã của tôi có thể là quá kém hiệu quả để chạy tốt.

Tôi không hoàn toàn quen thuộc với các chức năng ma trận của Numpy, vì vậy tôi phải giải quyết cho một vòng lặp chậm để quét từng cột thay vì một cái gì đó hiệu quả hơn. Có cách nào nhanh chóng để tìm hàng có pixel sáng nhất trên mỗi cột trong Numpy không?

Ngoài ra, có cách nào đáng tin cậy để cân bằng hình ảnh trước khi thực hiện sự khác biệt mà không làm mờ đường laser không?

+0

có thể cuối cùng, bạn có thể xóa tất cả các điểm có toạ độ y không nằm trong định vị 25% ~ 75%. Sau đó, bạn có thể nhận được kết quả tốt hơn, sau đó điền vào các giá trị bị thiếu bằng cách sử dụng locf..etc –

+0

@ B.Mr.W., Bạn đã đúng một phần. Vì laser được lắp bên dưới máy ảnh và song song với mặt phẳng tiêu cự của nó, tất cả các điểm laser phải nằm dưới hàng giữa, nghĩa là tất cả các điểm trên đều là tiếng ồn. Cảm ơn. – Cerin

Trả lời

1

Trước tiên, bạn có thể có thể rescale cường độ của hình ảnh tiêu cực của bạn trước khi trừ nó từ tích cực của bạn, để loại bỏ tiếng ồn hơn. Ví dụ có thể rescaling bởi các tỷ lệ của intesity trung bình có thể là một thử đầu tiên tốt?

Bạn cũng có thể thử đặt một ngưỡng: nếu tối đa của bạn ở dưới bất kỳ xứng, sau đó nó có lẽ không phải tia laser của bạn, nhưng một điểm ồn ào ...

Sau đó có NumPy có thể tìm thấy hàng/col tốt nhất với hàm argmax.

1

Đầu tiên nhập màu là laser và chỉ để lại màu đỏ (trong trường hợp này). Sau đó, áp dụng các hiệu ứng tương tự và kiểm tra kết quả.

Trong trường hợp này, bạn sẽ có kết quả ít bị ô nhiễm hơn nhiều. Result

Đã xảy ra sự cố khi phân tích màu đỏ trên cửa đã bị mất.

+0

Tôi không biết màu của laser, ngoài màu đỏ. Tôi không thể chỉ đơn giản là giả định mọi thứ màu đỏ là laser bởi vì có thể có vật màu đỏ trong cảnh. Giải pháp này phải được tự động hóa, vì vậy tôi không thể chỉ ra màu laser theo cách thủ công trong mỗi hình ảnh. – Cerin

+0

sau đó sử dụng hình ảnh của bạn, cuộn biểu đồ. có lẽ cách lớn nhất sẽ được tìm thấy một đường laser. ở lối vào của biểu đồ của bạn sẽ là bất kỳ pixel nào có hai pixel màu đen và hai điểm ảnh liền kề màu trắng. –

1

Tôi đã cố gắng làm điều gì đó. Tôi không nghĩ nó hoàn toàn mạnh mẽ. Nhưng trên ví dụ của bạn nó hoạt động tương đối tốt.

Tôi đã sử dụng tính năng phát hiện cạnh khó xác định để phát hiện cạnh trong hình ảnh "khác biệt" của bạn. Và sau đó áp dụng biến đổi dòng Hough như trong this tutorial. Vì vậy, tôi đã bắt đầu với hình ảnh đã xử lý của bạn (tôi gọi số lineDetection.jpg trong mã).

enter image description here

Đây là kịch bản chính thức

import cv2 
import numpy as np 

img = cv2.imread('lineDetection.jpg') 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
edges = cv2.Canny(gray,10,100) 
minLineLength = 50 
maxLineGap = 20 
lines = cv2.HoughLinesP(edges,0.05,np.pi/5000,10,minLineLength,maxLineGap) 
print(len(lines)) 
for i in range(len(lines)): 
    x1,y1,x2,y2 = lines[i][0] 
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2) 

cv2.imwrite('houghlines5.jpg',img) 

Trong dòng màu xanh lá cây được phát hiện trên hình ảnh xử lý. (Bạn có thể thêm nó vào hình ảnh ban đầu cho hiệu ứng đẹp hơn)

enter image description here

Hy vọng nó giúp.

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