Chroma Key Image Processing
Chroma key é uma técnica de pós-produção para juntar duas imagens ou sequência de vídeo anulando uma cor padrão. Este exemplo demonstra como remover o fundo (pano verde) and lidar com ruído e reflexos que podem adicionar um tom esverdeado a elementos da cena. Abaixo é apresentada a imagem de entrada deste exemplo. Esta imagem apresenta vários tons de cinza no pano de fundo assim como ruído em função da compressão.![]() A abordagem tem três passos: 1. Converte pixels verde em transparênciaNeste passo todos os pixels são processdor no espaço de cor HSV. Pixels verdes são convertidos em transparência. Dado um pixel p, este é considerado "verde" se:p.hue >= 60 AND p.hue <= 130 AND p.saturation >= 0.4 AND p.lightness >= 0.3 resultado: ![]() 2. Processa os pixels verdes restantes resultantes de refelxos e ruído de compressãoAlguns pixels verdes permancem na imagem e não podem ser removidos uma vez que fazem parte do objeto à frente. Isto é muito comum acontecer com cabelo:![]() Neste caso os pixels são filtrados e sua cor é balanceada para reduzir o tom de verde. ![]() 3. Alpha BoundaryO último passo adiciona transparência gradual para todo pixel e seus vizinhos que não são transparentes e que estão nas bordas do objeto à frente. Resultado:![]() package chromaToTransparency; import marvin.color.MarvinColorModelConverter; import marvin.image.MarvinImage; import marvin.io.MarvinImageIO; import static marvin.MarvinPluginCollection.*; public class ChromaToTransparency { public ChromaToTransparency(){ MarvinImage image = MarvinImageIO.loadImage("./res/person_chroma.jpg"); MarvinImage imageOut = new MarvinImage(image.getWidth(), image.getHeight()); // 1. Convert green to transparency greenToTransparency(image, imageOut); MarvinImageIO.saveImage(imageOut, "./res/person_chroma_out1.png"); // 2. Reduce remaining green pixels reduceGreen(imageOut); MarvinImageIO.saveImage(imageOut, "./res/person_chroma_out2.png"); // 3. Apply alpha to the boundary alphaBoundary(imageOut, 6); MarvinImageIO.saveImage(imageOut, "./res/person_chroma_out3.png"); } private void greenToTransparency(MarvinImage imageIn, MarvinImage imageOut){ for(int y=0; y<imageIn.getHeight(); y++){ for(int x=0; x<imageIn.getWidth(); x++){ int color = imageIn.getIntColor(x, y); int r = imageIn.getIntComponent0(x, y); int g = imageIn.getIntComponent1(x, y); int b = imageIn.getIntComponent2(x, y); double[] hsv = MarvinColorModelConverter.rgbToHsv(new int[]{color}); if(hsv[0] >= 60 && hsv[0] <= 130 && hsv[1] >= 0.4 && hsv[2] >= 0.3){ imageOut.setIntColor(x, y, 0, 127, 127, 127); } else{ imageOut.setIntColor(x, y, color); } } } } private void reduceGreen(MarvinImage image){ for(int y=0; y<image.getHeight(); y++){ for(int x=0; x<image.getWidth(); x++){ int r = image.getIntComponent0(x, y); int g = image.getIntComponent1(x, y); int b = image.getIntComponent2(x, y); int color = image.getIntColor(x, y); double[] hsv = MarvinColorModelConverter.rgbToHsv(new int[]{color}); if(hsv[0] >= 60 && hsv[0] <= 130 && hsv[1] >= 0.15 && hsv[2] >= 0.15){ if((r*b) !=0 && (g*g) / (r*b) > 1.5){ image.setIntColor(x, y, 255, (int)(r*1.4), (int)g, (int)(b*1.4)); } else{ image.setIntColor(x, y, 255, (int)(r*1.2), g, (int)(b*1.2)); } } } } } public static void main(String[] args) { new ChromaToTransparency(); } } |
||