Reconstruir un canal RGB perdido

11

Mire estas fotografías de escenas naturales, con uno de los canales RGB extraídos de ellas:

un bosque idílico sin rojo

Fuente (con rojo): https://en.wikipedia.org/wiki/File:Altja_j%C3%B5gi_Lahemaal.jpg

una costa antártica sin verde

Fuente (con verde): https://commons.wikimedia.org/wiki/File:2007_mather-lake_hg.jpg

un zorro rojo sin azul

Fuente (con azul): https://commons.wikimedia.org/wiki/File:Fox_01.jpg

Incluso sin uno de los canales, probablemente pueda distinguir qué colores se supone que son ciertas cosas, o al menos tener una buena idea si la reconstrucción del canal faltante es precisa.

Por ejemplo, aquí está la primera imagen con un canal rojo agregado nuevamente que es solo ruido aleatorio:

foto 1 con ruido agregado

Esta imagen claramente no es una reconstrucción precisa del canal rojo. Esto se debe a que las fotos de la naturaleza generalmente no usan todo el espectro RGB, sino solo un subconjunto de "colores de aspecto natural". Además, los tonos de rojo seguirán ciertos gradientes que se correlacionan con los demás.


Su tarea es construir un programa que tome una fotografía a la que se le haya quitado un canal e intente aproximar la imagen original lo más cerca posible reconstruyendo lo que cree que es el canal perdido.

Su programa se puntuará según cuán cerca coincida el canal faltante con el canal de la imagen original, contando el porcentaje de píxeles cuyos valores de ese canal están dentro de ± 15 (inclusive) del valor real en la imagen original (donde los valores rango de 0 a 255 como en un canal de color estándar de 8 bits).

Los casos de prueba en los que se puntuará su programa se pueden encontrar aquí (archivo zip de 9.04 MB, 6 imágenes). Actualmente solo contiene las tres imágenes de ejemplo anteriores y sus originales, pero agregaré algunas más más adelante para hacer el paquete completo una vez que las haya hecho.

Cada imagen se reduce y se recorta a 1024 x 768, por lo que tendrán el mismo peso en su puntaje. El programa que puede predecir la mayor cantidad de píxeles dentro de la tolerancia dada gana.

Joe Z.
fuente
1
¿Podría escribir un programa de puntuación, por ejemplo, en Python?
orlp
Llegaré a eso mañana. Ahora mismo necesito ir a la cama.
Joe Z.
¿Hay un límite para el tiempo de ejecución del programa?
Lause
@Lause El límite es su paciencia para que el programa realmente produzca resultados.
Joe Z.

Respuestas:

17

Python 3 + imagen-scikit

Simplemente establece el color del canal que falta al promedio de los otros dos.

import sys
from skimage import io, color

im = io.imread(sys.argv[1])
h, w, c = im.shape

removed_channel_options = {0, 1, 2}
for y in range(h):
    for x in range(w):
        if len(removed_channel_options) == 1: break
        removed_channel_options -= {i for i, c in enumerate(im[y][x]) if c > 0}
removed_channel = removed_channel_options.pop()

for y in range(h):
    for x in range(w):
        p = [float(c) / 255 for c in im[y][x][:3]]
        p = [sum(p)/2 if i == removed_channel else p[i]
             for i in range(3)]
        im[y][x] = [int(c*255) for c in p] + [255]*(c == 4)

io.imsave(sys.argv[2], im)

Y las imágenes restauradas:

bosque zorro glacial

orlp
fuente
3
promedio de los otros dos , aparentemente mucho más preciso (subjetivamente) de lo que hubiera imaginado. +1.
Trauma digital
2
Son una reminiscencia de daguerrotipos teñidos a mano de hace mucho tiempo. Muy agradable. +1
6

Lua, Love2D

Simplemente establece el canal que falta en el más pequeño de los dos canales restantes.

local inp = love.image.newImageData(arg[2])

local channels = {1, 2, 3}
local removed = nil
local removed_options = {true,true,true}

inp:mapPixel(function(x,y,r,g,b)
    local o = {r,g,b}
    for k,v in pairs(o) do
        if v > 0 then
            removed_options[k] = false
        end
    end
    return r,g,b
end)

for k,v in pairs(removed_options) do
    if v then
        removed = k
        break
    end
end
inp:mapPixel(function(x,y,r,g,b)
    local o = {r,g,b}
    o[removed] = math.min(o[removed%3+1], o[(removed+1)%3 + 1])
    return unpack(o)
end)

inp:encode('png', IMAGE:gsub("%.png", "2.png"))

Toma un nombre de archivo como argumento en la línea de comando.

Bosque zorro Nieve

Prima

Intenté configurar el canal faltante en 255- (a + b), sujetando el valor. En cuanto a "llenar el vacío". Los resultados son inútiles pero gloriosos.

Forrest Red Teal Zorro Amarillo Azul Nieve Púrpura Verde

Y con 255- (a + b) / 2

Bosque rojo cian aburrido Zorro Amarillo Azul Aburrido Nieve Púrpura Verde Aburrido

Un taco
fuente
Las imágenes se ven aún más realistas que la otra respuesta. ¡Gran trabajo! Por curiosidad, ¿qué sucede si haces 255- (a + b) / 2 en su lugar (sin necesidad de sujeción)?
ETHproductions
Los resultados son una versión menos saturada de los publicados anteriormente. Los agregaré a la respuesta para las risas.
ATaco
De hecho, me reí. Gracias.
Gabriel Benamy