2012-08-06 21 views
7

Devo generare alcune serie di immagini di prova per un'applicazione fotogrammetrica. Questi dovrebbero contenere oggetti semplici (dischi, rettangoli, ecc.) Con una posizione ben nota.Rendering sub-pixel in OpenGL - problema di accuratezza

Considerando un'immagine in scala di grigi a 8 bit di un rettangolo nero su sfondo bianco, un minimo spostamento osservabile (dopo l'interpolazione) deve essere di 1/256 pixel, in quanto vi sono 256 livelli di intensità possibili per ciascun pixel.

ho deciso di utilizzare OpenGL (con pitone + pyglet) per rendere tali immagini, come in seguito dovrò rendere più complicate (3d scena, coppie di immagini stereo)

Purtroppo, la migliore precisione che hanno raggiunto è intorno a pixel/10, la profondità dell'intensità totale non viene utilizzata.

È possibile fare meglio, idealmente - ottenendo una precisione di 1/256pixel? Qualche suggerimento su come farlo, per favore?

codice di esempio, generando immagini di un disco parziale, spostato 0,01 pixel più in ciascun frame

#-*- coding: utf-8 -*- 
import pyglet 
from pyglet.gl import * 
from PIL import Image, ImageGrab 

config = pyglet.gl.Config(width = 800, height = 600, sample_buffers=1, samples=16) 
window = pyglet.window.Window(config=config, resizable=True) 
window.set_size(800, 600) 

printScreenNr = 0 

@window.event 
def on_draw(): 
    global printScreenNr 
    window.clear() 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glLoadIdentity() 
    glEnable(GL_LINE_SMOOTH) 
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); 

    glTranslated(200, 200,0) 

    circleQuad = gluNewQuadric() 
    glTranslated(200+(printScreenNr*0.01), 0, 0) 
    gluPartialDisk(circleQuad, 0, 50, 500, 500, 0, 180) 

@window.event 
def on_resize(width, height): 
    glViewport(0, 0, width, height) 
    glMatrixMode(GL_PROJECTION) 
    glLoadIdentity() 
    glOrtho (0, width, height, 0, 0, 1); 
    glMatrixMode(GL_MODELVIEW) 
    return pyglet.event.EVENT_HANDLED 

@window.event 
def on_text(text): 
    global printScreenNr 
    if(text == "p"): 
     pyglet.image.get_buffer_manager().get_color_buffer().save('photo'+str(printScreenNr)+'.tiff') 
     printScreenNr += 1 

pyglet.app.run() 

(il codice precedente utilizza gluPartialDisk, ma Ho testato il problema utilizzando anche quadrilateri, precisione dei risultati fatto non diverso)

+0

Hai provato a utilizzare una profondità di colore a 32 bit? La ragione per cui dico questo è che i percorsi a 32 bit sono i percorsi di codice più utilizzati e quindi più curati nei driver grafici al giorno d'oggi. Se funziona, è possibile eseguire successivamente un ridimensionamento della profondità del colore di alta qualità. – Ani

+0

provato, ma non ha modificato i risultati ... ancora, grazie – Pietro

risposta

4

Un modo semplice per farlo è ridimensionare l'immagine di un fattore. Se ridimensionate l'immagine per 4.0, 16 pixel originali verranno uniti in un pixel di destinazione che fornisce 16 sfumature di grigio quando si ridimensiona un'immagine pura B & W.

Ma c'è un problema che probabilmente spiega il tuo problema. Se avete questo:

...##### 
    ...##### 
    ...##### 
    ...##### 

(a sinistra: bianco, a destra: nero rettangolo pieno), allora si hanno 12 bianco e 4 pixel neri che contribuiscono a un singolo pixel di uscita. Per ottenere 1 pixel nero, l'ingresso avrebbe bisogno di essere questo:

....#### 
    ....#### 
    ....#### 
    ...##### 

Vedi? Anche se la scatola nera perde solo un pixel nello spazio bianco, lo fa quattro volte. Quindi, per assicurarti che il tuo codice di rendering subpixel funzioni, devi guardare i singoli pixel o gli angoli, non i bordi.

+0

Il rendering di un'immagine (via) più grande sarebbe una soluzione, ma penso che la dimensione dello schermo sia un limite? Quindi non sarà di grande aiuto Circa l'altra parte della risposta, non sono sicuro di aver capito correttamente ... se l'immagine è stata ridimensionata 4x (in ogni direzione), che dà 4 possibili sfumature quando si osserva un bordo (e 16 quando si osserva un punto) ma ancora, dovrebbe essere in qualche modo possibile generare un bordo posizionato con accuratezza a profondità completa – Pietro

+0

Come? il bordo ha solo quattro posizioni diverse, quindi puoi ottenere solo 4 delle 16 sfumature. –

+0

correggimi se ho ancora torto Supponiamo che l'immagine sia stata ridimensionata di 256 fattori. Un bordo avrebbe 256 posizioni, e un punto: 256^2 (che sarebbe arrotondato) poteva essere, se tale cosa è possibile fare in OpenGL (in questo caso le prestazioni non è un problema), ma io pensare che le immagini che soddisfano questi requisiti siano generalmente possibili da generare. La mia domanda è giusta: come farlo .. – Pietro

1

Anche se si utilizza la proiezione ortogonale, GL_PERSPECTIVE_CORRECTION_HINT potrebbe influire sulla precisione del rendering. Almeno ricordo vagamente glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); risolvendo alcune lacune nella mia scena proiettata ortogonalmente molti anni fa.

+0

Grazie, ha aggiunto, non ha cambiato i risultati al momento, ma forse sarà necessario nella futura modalità 3D – Pietro

Problemi correlati