2013-01-04 38 views
6

tôi có một loạt các hình ảnh như thế này:hình ảnh đường cong phù hợp

enter image description here

Các dữ liệu tương ứng là không có sẵn. Tôi cần phải tự động lấy khoảng 100 điểm (thường xuyên x-khoảng cách) trên đường cong màu xanh. Tất cả các đường cong đều rất giống nhau, vì vậy tôi cần ít nhất 1 pixel chính xác, nhưng pixel phụ sẽ được ưu tiên hơn. Tin tốt là tất cả các đường cong bắt đầu từ 0,0 và kết thúc ở mức 1,1, vì vậy chúng ta có thể quên lưới.

Bất kỳ gợi ý nào về libs Python có thể giúp hoặc cách tiếp cận nào khác? Cảm ơn !

+0

Câu hỏi thú vị, tôi đang làm việc trên một giải pháp, nhưng độ chính xác của pixel phụ là không thể. –

+1

Chỉ bán tự động nhưng vẫn liên quan đến câu hỏi, ứng dụng web này có thể làm điều kỳ diệu: http://arohatgi.info/WebPlotDigitizer/ –

Trả lời

6

Tôi đã lưu hình ảnh của bạn vào một tệp 14154233_input.png. Sau đó, chương trình này

import pylab as plt 
import numpy as np 

# Read image from disk and filter all grayscale 
im = plt.imread("14154233_input.png")[:,:,:3] 
im -= im.mean(axis=2).reshape(im.shape[0], im.shape[1], 1).repeat(3,axis=2) 
im_maxnorm = im.max(axis=2) 

# Find y-position of remaining line 
ypos = np.ones((im.shape[1])) * np.nan 
for i in range(im_maxnorm.shape[1]): 
    if im_maxnorm[:,i].max()<0.01: 
     continue 
    ypos[i] = np.argmax(im_maxnorm[:,i]) 

# Pick only values that are set 
ys = 1-ypos[np.isfinite(ypos)] 
# Normalize to 0,1 
ys -= ys.min() 
ys /= ys.max() 

# Create x values 
xs = np.linspace(0,1,ys.shape[0]) 

# Create plot of both 
# read and filtered image and 
# data extracted 
plt.figure(figsize=(4,8)) 
plt.subplot(211) 
plt.imshow(im_maxnorm) 
plt.subplot(212, aspect="equal") 
plt.plot(xs,ys) 
plt.show() 

Tạo âm mưu này:

Ausgabe

Sau đó, bạn có thể làm với xsys bất cứ điều gì bạn muốn. Có lẽ bạn nên đặt mã này trong một hàm trả về xs và ys hoặc như vậy.

Người ta có thể cải thiện độ chính xác bằng cách lắp gaussians trên mỗi cột hoặc hơn. Nếu bạn thực sự cần nó, hãy nói cho tôi biết.

+0

Tôi không thực tế với pylab, tôi có thể yêu cầu bạn giải thích cách 'im - = im.mean (axis = 2) .reshape (im.shape [0], im.shape [1], 1) .lặp lại (3, trục = 2) 'dòng hoạt động? –

+0

Chắc chắn. imread cung cấp cho chúng ta hình ảnh RGBA, tức là mảng của chúng tôi có hình dạng (x, y, 4), mà tôi ngay lập tức giảm bằng cách loại bỏ alpha ([:,:,: 3] trong dòng trước đó). Sau đó tôi muốn thiết lập tất cả các màu với màu đỏ = xanh = xanh (tất cả các màu xám từ đen sang trắng) thành đen, sao cho chỉ có đường màu xanh dương vẫn còn. Tôi làm điều này bằng cách trừ đi, đối với mỗi pixel, giá trị trung bình của các giá trị R, G và B từ mỗi pixel. Nếu chúng bằng nhau, tất cả trở thành số không. '.mean (axis = 2)' tính giá trị trung bình, tạo mảng 2d; '.esheshape()' làm cho nó 3d một lần nữa, bằng cách thêm một 3. mờ của len 1; '.repeat()' đặt lại hình dạng của mảng thành 'im' –

2

Đầu tiên, hãy đọc những hình ảnh qua

from scipy.misc import imread  
im = imread("thefile.png") 

này đưa ra một mảng NumPy 3D với không gian thứ ba là kênh màu (RGB + alpha). Đường cong nằm trong kênh màu xanh dương, nhưng lưới cũng ở đó. Nhưng trong kênh màu đỏ, bạn có lưới và không phải là đường cong. Vì vậy, chúng tôi sử dụng

a = im[:,:,2] - im[:,:,0] 

Bây giờ, chúng tôi muốn vị trí tối đa dọc theo mỗi cột. Với độ chính xác một pixel, nó được cho bởi

y0 = np.argmax(a, axis=0) 

Kết quả của số không là khi không có đường cong màu xanh trong cột, tức là bên ngoài khung. Bật có thể nhận được các giới hạn của khung bằng cách

xmin, xmax = np.where(y0>0)[0][[0,-1] 

Với điều này, bạn có thể rescale trục x.

Sau đó, bạn muốn độ phân giải subpixel. Chúng ta hãy tập trung vào một cột duy nhất

f=a[:,x] 

Chúng tôi sử dụng một sự lặp lại duy nhất của phương pháp Newton để tinh chỉnh vị trí của một cực trị

y1 = y0 - f'[y]/f''[y] 

Lưu ý rằng chúng ta không thể lặp lại nữa vì việc lấy mẫu kín đáo. Nontheless, chúng tôi muốn một xấp xỉ tốt của các dẫn xuất, vì vậy chúng tôi sẽ sử dụng một chương trình 5 điểm cho cả hai.

coefprime = np.array([1,-8, 0, 8, -1], float) 
coefsec = np.array([-1, 16, -30, 16, -1], float) 
y1 = y0 - np.dot(f[y0-2:y0+3], coefprime)/np.dot(f[y0-2:y0+3], coefsec) 

P.S. : Thorsten Kranz nhanh hơn tôi (ít nhất là ở đây), nhưng câu trả lời của tôi có độ chính xác subpixel và cách tôi trích xuất đường cong màu xanh có lẽ dễ hiểu hơn.

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