2012-02-12 57 views
17

Tôi nghĩ rằng điều này sẽ dễ dàng hơn nhưng sau một thời gian tôi cuối cùng đã từ bỏ việc này, ít nhất là trong một vài giờ ...Xếp chồng hình ảnh thiên văn học với Python

Tôi muốn tạo lại dấu vết này sao hình ảnh từ một tập hợp các hình ảnh timelapse. Lấy cảm hứng từ điều này: Inspiration

The original author sử dụng khung video có độ phân giải thấp được chụp bằng VirtualDub và kết hợp với imageJ. Tôi tưởng tượng rằng tôi có thể dễ dàng tái tạo quy trình này nhưng với một cách tiếp cận có ý thức về bộ nhớ hơn với Python, vì vậy tôi có thể sử dụng the original high-resolution images để có kết quả tốt hơn.

Ý tưởng của thuật toán của tôi rất đơn giản, hợp nhất hai hình ảnh cùng một lúc và sau đó lặp lại bằng cách hợp nhất hình ảnh kết quả với hình ảnh tiếp theo. Điều này đã thực hiện hàng trăm lần và cân đúng cách để mỗi hình ảnh có cùng đóng góp cho kết quả cuối cùng.

Tôi khá mới với python (và tôi không có lập trình viên chuyên nghiệp), nhưng nhìn xung quanh nó xuất hiện với tôi Thư viện hình ảnh Python rất chuẩn, vì vậy tôi quyết định sử dụng nó (đúng tôi nếu bạn nghĩ cái gì khác sẽ tốt hơn).

Dưới đây là những gì tôi có cho đến nay:

#program to blend many images into one 
import os,Image 
files = os.listdir("./") 
finalimage=Image.open("./"+files[0]) #add the first image 
for i in range(1,len(files)): #note that this will skip files[0] but go all the way to the last file 
    currentimage=Image.open("./"+files[i]) 
    finalimage=Image.blend(finalimage,currentimage,1/float(i+1))#alpha is 1/i+1 so when the image is a combination of i images any adition only contributes 1/i+1. 
    print "\r" + str(i+1) + "/" + str(len(files)) #lousy progress indicator 
finalimage.save("allblended.jpg","JPEG") 

này làm những gì nó nghĩ đến nhưng hình ảnh kết quả là bóng tối, và nếu tôi chỉ đơn giản là cố gắng để nâng cao nó, đó là điều hiển nhiên rằng thông tin bị mất thiếu do chiều sâu trong các giá trị của pixel. (Tôi không chắc chắn những gì các thuật ngữ thích hợp ở đây là, độ sâu màu, độ chính xác màu sắc, kích thước pixel). Dưới đây là kết quả cuối cùng sử dụng hình ảnh độ phân giải thấp:

Low resolution result

hoặc một tôi đã cố gắng với đầy đủ 4k bởi độ phân giải 2k (từ một tập hợp các hình ảnh):

High resolution result with another set of images

Vì vậy, Tôi đã cố khắc phục sự cố bằng cách đặt chế độ hình ảnh:

firstimage=Image.open("./"+files[0]) 
size = firstimage.size 
finalimage=Image.new("I",size) 

nhưng rõ ràng là Image.blend d oes không chấp nhận chế độ hình ảnh đó.

ValueError: image has wrong mode

Bất kỳ ý tưởng nào?

(Tôi cũng đã cố gắng làm cho hình ảnh "ít đen tối" bằng cách nhân nó trước khi kết hợp chúng với im.point (lambda i: i * 2) nhưng kết quả chỉ là xấu)

+1

Hình ảnh của bạn không có trọng số như nhau. Ví dụ, hình ảnh đầu tiên của bạn có opacity '1/(1 + 1) = 0,5', trong khi hình ảnh thứ 9 của bạn có độ mờ' 0.1'. – Blender

+1

Máy xay sinh tố, tôi nghĩ nó có trọng số như nhau. khi i = 0, 1/(i + 1) = 1, thì đối với lần lặp đầu tiên có hình ảnh là 0,5 vì 0,5 khác được chụp bởi ảnh thứ hai (tệp [1]), và sau đó khi i = 2 , tệp [2] có trọng số là 0,33, để hai kết quả đầu tiên được kết hợp với tổng số 0,66 .. tức là 0,33 mỗi. Vì vậy, hình ảnh thứ 9 thực sự có 0,1 alpha, nhưng điều đó có nghĩa là 8 đầu tiên có độ mờ kết hợp là 0,9, tức là 0,1 mỗi hình ảnh (xem tệp [0]). – JunCTionS

+3

Không, @Blender là đúng, bạn cần một * trọng lượng không đổi cho mỗi hình ảnh *, có nghĩa là '1/len (tệp)'. Nếu bạn có 2 hình ảnh tổng cộng mỗi hình ảnh được trọng lượng 0,5. Nếu bạn có tổng cộng 10 hình ảnh, mỗi hình ảnh sẽ có trọng số 0,1. –

Trả lời

20

Vấn đề ở đây là bạn là tính trung bình độ sáng ở mỗi pixel. Điều này có vẻ hợp lý nhưng nó thực sự không phải là những gì bạn muốn ở tất cả - những ngôi sao sáng sẽ nhận được "trung bình đi" bởi vì họ di chuyển trên hình ảnh. Đi bốn khung hình sau đây:

1000 0000 0000 0000 
0000 0100 0000 0000 
0000 0000 0010 0000 
0000 0000 0000 0001 

Nếu bạn tính trung bình những, bạn sẽ nhận được:

0.25 0 0 0 
0 0.25 0 0 
0 0 0.25 0 
0 0 0 0.25 

Khi bạn muốn:

1000 
0100 
0010 
0001 

Thay vì pha trộn các hình ảnh mà bạn có thể thử dùng các hiển thị tối đa trong bất kỳ hình ảnh nào cho mỗi pixel.Nếu bạn có PIL, bạn có thể thử chức năng nhẹ hơn trong ImageChops.

from PIL import ImageChops 
import os, Image 
files = os.listdir("./") 
finalimage=Image.open("./"+files[0]) 
for i in range(1,len(files)): 
    currentimage=Image.open("./"+files[i]) 
    finalimage=ImageChops.lighter(finalimage, currentimage) 
finalimage.save("allblended.jpg","JPEG") 

Đây là những gì tôi nhận: Low res image set stacked

EDIT: Tôi đọc bài đăng trên Reddit và thấy rằng ông thực sự kết hợp hai cách tiếp cận - một cho những con đường mòn sao và một khác nhau cho Trái Đất . Đây là cách thực hiện tốt hơn mức trung bình bạn đã thử, với trọng số phù hợp. Tôi đã sử dụng mảng numpy cho bộ nhớ trung gian thay vì mảng hình ảnh uint8.

import os, Image 
import numpy as np 
files = os.listdir("./") 
image=Image.open("./"+files[0]) 
im=np.array(image,dtype=np.float32) 
for i in range(1,len(files)): 
    currentimage=Image.open("./"+files[i]) 
    im += np.array(currentimage, dtype=np.float32) 
im /= len(files) * 0.25 # lowered brightness, with magic factor 
# clip, convert back to uint8: 
final_image = Image.fromarray(np.uint8(im.clip(0,255))) 
final_image.save('all_averaged.jpg', 'JPEG') 

Đây là hình ảnh, sau đó bạn có thể kết hợp với các đường nhỏ của ngôi sao từ hình trước đó. Low res images added together

+1

Tuyệt vời !! Cảm ơn nhiều. [Đây là kết quả cuối cùng với hình ảnh có kích thước đầy đủ gốc] (http://i.imgur.com/P9mzc.jpg) (mặc dù một chút bị hạ cấp theo giới hạn kích thước của imgur) [1]: http: // i .imgur.com/P9mzc.jpg – JunCTionS

+0

@JunCTionS Không phải lo lắng, trông rất tuyệt. Tôi thực sự đọc nhận xét của Reddit và anh ấy đã làm điều tương tự như tôi đã gợi ý cho những con đường mòn sao, nhưng một cái gì đó giống như cách tiếp cận trung bình ban đầu của bạn cho trái đất. Tôi sẽ có một vết nứt nhanh ở đó và thêm nó như là một chỉnh sửa. – simonb