Así que he estado en este problema durante aproximadamente un año y no he podido resolverlo. Me di por vencido hace un tiempo, pero ahora estoy investigando y listo para obtener una respuesta.
Estoy tratando de fingir una exposición prolongada tomando múltiples fotos RAW y haciendo algo con los valores del filtro Bayer para obtener el efecto de haber dejado el obturador abierto durante tanto tiempo.
La idea que tengo en mente es que, intuitivamente, la exposición prolongada funciona dejando el obturador abierto durante más tiempo, por lo que los valores del sensor de luz (que almacenan las imágenes RAW) son simplemente una agregación de múltiples valores de fotos más cortas .
Por ejemplo, si tengo tres fotos de 1/3 de segundo de duración tomadas sin mover la cámara, deberían almacenar la misma información que una foto de 1 segundo de duración.
El problema que tengo es cómo puedo cuantificar esa agregación. Descubrí que muchos métodos diferentes fallan y no estoy seguro de por qué. Si simplemente promedio las múltiples fotos, obtengo una gran reducción de ruido . Así que es bueno tener esa parte. Más tarde puedo usar Camera Raw para iluminar la foto y obtendré una aproximación cercana a lo que habría obtenido con una exposición prolongada de 1 segundo. El problema es que quiero hacer eso en el dispositivo. Actualmente estoy usando un iPhone para probar, pero no creo que eso deba importar.
Estoy usando tres exposiciones de 1/3 de segundo para tratar de falsificar una foto de 1 segundo. Mi fórmula actual es simple:
out_picture[x][y] = picture1[x][y] + picture2[x][y] + picture3[x][y]
El problema es que eso me da imágenes realmente rosadas como esta:
Probé múltiples variaciones diferentes de la fórmula anterior. Una que pensé que era prometedora era la derivada de la función sigmoidea . La razón por la que utilicé la derivada del sigmoide es porque realicé un estudio de caso en el que estudié el efecto de las salidas RGB finales en función del valor del control deslizante "EV" en Photoshop Camera Raw y encontré un patrón similar al sigmoide. Esto es lo que parece cuando lo trazo para algunos píxeles:
Así que pensé que tal vez la derivada del sigmoide (cambios altos para valores medios, cambios bajos para valores de filtro altos y bajos) arreglaría las cosas. Normalicé los valores del filtro a un rango de 0-1 usando el nivel de negro de la cámara y el valor máximo de bits. Hice algunas modificaciones a la derivada para que encajara dentro del rango de valores 0-1, esta es la función con la que terminé. Luego multipliqué por el número de fotografías tomadas, para emular el EV
control deslizante en Camera Raw.
Aquí está la fórmula para eso (en python):
def exposureAdjust(x):
black_level = 528 ## iPhone RAW Photos have a black_level of 528
max_pixel_value = 2**14 - 1 ## 14-bit depth
normalized = (x - black_level)/max_pixel_value ## now x is between [0,1]
EV = num_pics ## faking EV value
adjustment = EV * (np.exp(-10 *(x - 0.25)))/(np.exp(-10*(x - 0.25)) + 1)^2
return min(x * (1+adjustment), max_pixel_value) ## Cap at 2**14
num_pics = 3
out_picture[x][y] = picture1[x][y] + picture2[x][y] + picture3[x][y]
out_picture[x][y] = exposureAdjust(out_picture[x][y]/3)
Ejecutando esta fórmula, obtengo un resultado similar:
Como puede ver, todavía es rosado. Las fotos de arriba son JPEG, sí, pero en realidad estoy trabajando con RAW. Solo tuve que subirlos como archivos JPEG para poder adjuntarlos en línea.
El rosa sucede cuando falta el verde. La cámara tiene un diseño de filtro bayer de RGGB, pero realmente no veo cómo podría obtener este efecto. Alguien tiene alguna idea de cuál es el culpable aquí y cómo puedo ajustarlo programáticamente. Tengo toda la canalización configurada. Solo necesito la fórmula, pero de alguna manera no funciona. He codificado esto en Python y Swift, y los resultados son los mismos. Definitivamente hay un problema con la fórmula que usa los valores de filtro RAW Bayer. Creo que este es un desafío genial, pero he llegado al final de mi ingenio en esto.
¿Alguna idea?
exposureAdjust
aplicar la función. ¿Parece que el canal verde debe ajustarse de manera diferente?Observaciones:
Está sumando los valores de cada píxel, pero su exposureAdjust()
función asume que después del condicionamiento, cada píxel estará en el rango [0, 1). Esto no es correcto. Suponga que el valor de un píxel en cada una de las 3 imágenes de entrada es, digamos, 50 % de escala completa (por lo tanto, 2 13 = 8192). Sumando eso tres veces da 3 * 8192 = 24,576. Luego, el resultado posterior normalized = (x - black_level)/max_pixel_value
es aproximadamente 1.47, definitivamente no normalizado a menos de 1.
Elimine su adjustment =
línea sigmoidea hasta que resuelva el resto de la lógica (como arriba). Aquí hay un gráfico de su función sigmoidea:
Tenga en cuenta que para los valores de x por encima de 0,4, el aumento de x produce rápidamente valores más pequeños de y (su valor "ajustado". A modo de comparación, un valor no ajustado debería corresponder a la gráfica lineal y = x en el gráfico.
Para la normalización (suponiendo entradas correctamente delimitadas de [0, ]), probablemente también max_pixel_value - 1
debería reducir el denominador (es decir, ). Si no lo hace, entonces sus valores normalizados están en el rango de [0, ∼0.969) (precisamente, (2 13 - 511) / (2 14 - 1)).black_level
normalized = (x - black_level)/(max_pixel_value - black_level)
Sus resultados son decididamente magenta y eso es lo opuesto a lo que deberían ser. Deben ser verdes para un bayer RGB sin corregir.
Sospecho que su corrección sigmoidea observada estuvo fuertemente influenciada por los datos sin procesar que ya tenían una corrección de balance de blancos aplicada en ACR. Es posible que incluso obtenga una "corrección duplicada" en este punto, pero no lo sé.
Este artículo sobre Uni-WB tiene mucha información sobre las correcciones/métodos de datos sin procesar y los factores de corrección de WB. http://www.guillermoluijk.com/tutorial/uniwb/index_en.htm
scottbb
scottbb
scottbb
josevictor
mattdm
mattdm
josevictor
scottbb
josevictor