2015-06-13 19 views
7

Piszę kod, którego częścią jest odczytywanie źródła obrazu i wyświetlanie go na ekranie, z którego użytkownik może korzystać. Potrzebuję również wyostrzonych danych obrazu. Używam następujących do odczytu danych i wyświetlić go w pyGameJak zaprezentować numpy array na powierzchni pygame?

def image_and_sharpen_array(file_name): 
    #read the image data and return it, with the sharpened image 
    image = misc.imread(file_name) 

    blurred = ndimage.gaussian_filter(image,3) 
    edge = ndimage.gaussian_filter(blurred,1) 
    alpha = 20 
    out = blurred + alpha*(blurred - edge) 
    return image,out 

#get image data 
scan,sharpen = image_and_sharpen_array('foo.jpg') 
w,h,c = scan.shape 


#setting up pygame 
pygame.init() 
screen = pygame.display.set_mode((w,h)) 

pygame.surfarray.blit_array(screen,scan) 
pygame.display.update() 

a obraz jest wyświetlany na ekranie tylko obraca i rewersu. Czy wynika to z różnic między misc.imread i pyGame? Czy to z powodu czegoś złego w moim kodzie?

Czy jest inny sposób na zrobienie tego? Większość rozwiązania, które przeczytałem, polegało na zapisaniu liczby, a następnie przeczytaniu jej za pomocą `pyGame '.

Odpowiedz

1

Każda biblioteka ma własny sposób interpretacji macierzy obrazów. Przez "obrócony" myślę, że masz na myśli transpozycję. W ten sposób PyGame pokazuje niezliczone tablice. Jest wiele sposobów na to, aby wyglądały "poprawne". W rzeczywistości istnieje wiele sposobów na wyświetlenie tablicy, co daje pełną kontrolę nad reprezentacją kanału i tak dalej. W wersji 1.9.2 jest to najszybsze renderowanie tablic jakie kiedykolwiek mogłem osiągnąć. (Uwaga dla wcześniejszej wersji to nie zadziała!). Funkcja ta wypełni powierzchnię tablicy:

def put_array(surface, myarr):   # put array into surface 
    bv = surface.get_view("0") 
    bv.write(myarr.tostring()) 

Jeśli to nie działa, użyj tego, powinny pracować wszędzie:

# put array data into a pygame surface 
def put_arr(surface, myarr): 
    bv = surface.get_buffer() 
    bv.write(myarr.tostring(), 0) 

Prawdopodobnie jeszcze się nie to, co chcesz, więc jest transponowane lub zamieniłem kanały kolorów. Chodzi o to, aby zarządzać tablicami w tej formie, w której mieści się ten bufor powierzchni. Aby dowiedzieć się, jaka jest prawidłowa kolejność kanałów i kolejność osi, użyj biblioteki openCV (cv2.imread (nazwa pliku)). Z openCV otwierasz obrazy w kolejności BGR w standardzie i ma wiele funkcji konwersji. Jeśli dobrze pamiętam, podczas zapisu bezpośrednio do bufora powierzchni, BGR jest poprawną kolejnością dla 24 bitów i BGRA dla 32 bitowej powierzchni. Możesz więc spróbować wstawić macierz obrazu, która dostaniesz z pliku za pomocą tej funkcji i zamigotać na ekranie.

Istnieją inne sposoby rysowania tablic np. tutaj jest cały zestaw funkcji pomocniczych http://www.pygame.org/docs/ref/surfarray.html
Ale nie polecam używania go, ponieważ powierzchnie nie są przeznaczone do bezpośredniej manipulacji pikselami, prawdopodobnie utracisz referencje. Mała wskazówka: Aby wykonać "test sygnalizacyjny", użyj obrazu podobnego do tego. Natychmiast zobaczysz, czy coś jest nie tak, po prostu załaduj jako tablicę i spróbuj wyrenderować.

enter image description here

1

Moja sugestia dotyczy korzystania z modułu pygame.transform. Dostępne są metody flip i rotate, których można użyć do transformacji. Sprawdź dokumentację na ten temat.

Moja rekomendacja to zapisanie obrazu wyjściowego do nowego Surface, a następnie zastosowanie transformacji i blitowanie na ekranie.

temp_surf = pygame.Surface((w,h)) 
pygame.surfarray.blit(temp_surf, scan) 

'''transform temp_surf''' 

screen.blit(temp_surf, (0,0)) 

Nie mam pojęcia, dlaczego tak jest. Prawdopodobnie ma to związek z kolejnością przenoszenia osi z macierzy 2d do pygame Surface.

0

często użyć numpy swapaxes() metodę: W tym przypadku wystarczy odwrócić X i osi Y (numer osi 0 i 1), przed wyświetleniem naszej tablicy:

return image.swapaxes(0,1),out 
1

Pomyślałem, że technico stanowi dobre rozwiązanie - po prostu trochę ubogo na informacje. Zakładając get_arr() jest funkcją, która zwraca tablicę pikseli:

pixl_arr = get_arr() 
pixl_arr = numpy.swapaxes(pixl_arr, 0, 1) 
new_surf = pygame.pixelcopy.make_surface(pixl_arr) 
screen.blit(new_surf, (dest_x, dest_y)) 

Alternatywnie, jeśli wiesz, że obraz będzie zawsze o tych samych wymiarach (jak w iteracja klatek pliku wideo lub gif), to byłoby bardziej skuteczne ponowne wykorzystanie tej samej powierzchni:

pixl_arr = get_arr() 
pixl_arr = numpy.swapaxes(pixl_arr, 0, 1) 
pygame.pixelcopy.array_to_surface(old_surf, pixl_arr) 
screen.blit(old_surf, (dest_x, dest_y)) 

YMMV, ale jak na razie działa to dobrze dla mnie.

Powiązane problemy