A técnica de Chroma Key , ou seja, a substituição de uma determinada cor, com o outro (ou outra fonte), a última década tem explodida, uma vez mais com quiralidade considerável, graças à tecnologia cada vez mais generalizada presente na película e no processamento de imagens digitais. Se no passado o Chroma Key foi usado muitas vezes com resultados pobres, hoje é uma técnica aplicada de forma contínua, mesmo em contextos e situações imagináveis ou não, sempre reconhecível, como evidenciado pelo vídeo abaixo:
Há mostreò agora como aplicá-los técnica bastante simples Chroma Key no ambiente Adobe Flash. exemplo que eu fiz , eu usei um objeto de vídeo cortada para o seu quarto (ou WebCam que é).
Nota: nas amostras de código abaixo, e na demonstração filme do Flash , eu usei o preto como a cor do chroma! Na verdade, como você deve saber, são usados painéis ou folhas de cor azul (daí o nome de Blue Screen) ou verde (Pantone 354)! ; dove è
AAè il canale alpha di trasparenza. Você também vai notar que os valoresuintcores são tudo na forma0xAARRGGBB, ondeAAé o canal alfa para transparência.
dell'oggetto BitmapData . threshold ( ) è un metodo molto potente e al tempo stesso molto semplice da utilizzare. Para processar a imagem I utilizado o método de threshold ( ) objeto BitmapData . threshold ( ) é um método muito eficaz e, ao mesmo tempo, muito fácil de usar. Ela permite realizar um controlo de um pixel por pixel Bitmap , e descobriram que uma cor (mascarado) é igual, não igual, maior ou menor do que o outro e sostituiendolo com um dado valor. O protótipo é a seguinte:
1 2 3 4 5 6 7 8 | threshold ( sourceBitmapData : BitmapData , limiar public function (sourceBitmapData: BitmapData , , sourceRect: retângulo , , destPoint: Ponto , , operação: Cordas , uint , limiar: uint , uint = 0 , color: uint = 0, uint = 0xFFFFFFFF , mask: uint = 0xFFFFFFFF, = false ) : uint copysource: Boolean = false): uint |
-
sourceBitmapDatasão os dados de bitmap na qual operam. Essa fonte pode ser diferente ou o mesmo que oBitmapDatano qual você está trabalhando - che definisce l'area su cui eseguire l'operazione
sourceRecté um ponteiro para um objeto do tipoRectangleque define a área em que para realizar a operação - che definisce le coordinate
xedydi destinazione: quasi sempre 0,0destPointé um ponteiro para um objeto do tipoPointque define as coordenadasxeyde destino: quase sempre 0.0 -
operationesta é uma string que define a operação a ser realizada sobre os pixels (ver detalhes abaixo), e pode ter os seguintes valores:"<", "<=", ">", ">=", "==", "!=" -
thresholdé um unsigned int, um inteiro sem sinal, indicando a cor (ou valor limite) para comparar com os dados de pixel do bitmap, por exemplo0x00FF0000 -
coloré um unsigned int, um inteiro sem sinal, indicando a cor a ser substituída, se a operação de comparação é bem sucedida - e ai pixel della bitmap sorgente
maské um unsigned int, um inteiro sem sinal, indicando que a máscara deve ser aplicada ao parâmetro dethresholde os pixels de fonte mapa de bits - copierà il valore corrente quando l'operazione di confronto fallisce
copySourceé um boolean que se definir atrueirá copiar o valor atual, quando a operação de comparação não
O método retorna uma uint que representa o número de pixels alterados. A operação que realiza o método pode ser resumida da seguinte forma:
- A partir das coordenadas definido na
sourceRect - , cioè viene eseguita l'operazione di AND logico tra i due valori:
(pixelLetto & mask)É lido o valor do pixel emsourceBitmape é aplicada à máscara,mask, ou seja, a operação é realizada pela lógica E dos dois valores:(pixelLetto & mask) - O valor obtido é comparado com
(threshold & mask), também mascarado, aplicando-se a operação de comparação deoperation - viene impostato quel pixel su
colorSe a comparação retornartrue, então a partir dedestPointestá definido que o pixel dacolor - a
true: in questo caso viene copiato il valore così com'è Se a comparação retornarfalse, não realizar qualquer operação, a menos que defina o parâmetrocopySourceatrue: neste caso, o valor é copiado como é
No exemplo que eu fiz você vai notar quatro caixas com quatro imagens do quarto:
Lembre-se de permitir o acesso à sala: Se você tem mais quartos comunicantes
escolher o caminho certo com o botão direito de definições
: A primeira caixa no canto superior esquerdo, vídeo original, o vídeo é o que parece quando usamos o objeto Camera anexado ao objeto Video :
1 2 |
Imediatamente a seguir são a caixa de Threshold, este é gerado da seguinte maneira:
1 2 3 4 | / / Threshold BitmapData = new BitmapData ( vid_video . width , vid_video . height , true ) ; var simpleBitmapData: BitmapData = new BitmapData (largura vid_video., vid_video altura, é verdade.); Bitmap = new Bitmap ( simpleBitmapData ) ; var simpleBitmap: Bitmap = new Bitmap (simpleBitmapData); simpleBitmap ) ; addChild (simpleBitmap); |
Em essência, este cria a primeira instância de um objecto BitmapData o tamanho do vídeo. Este está ligado a um objecto Bitmap , o qual pode ser adicionado à fase. (impostate almeno un valore di 30 fotogrammi al secondo nel vostro progetto): Neste ponto, pode-se aplicar o método de threshold , inserindo nosso procedimento dentro do evento ENTER_FRAME (definido para um valor de pelo menos 30 quadros por segundo em seu projeto):
1 2 3 4 5 6 7 8 9 10 11 12 13 | Event . ENTER_FRAME , addEventListener ( Evento . ENTER_FRAME, e : Event ) : void { function (e: Evento ): void { . draw ( vid_video ) ; .. simpleBitmap bitmapData empate (vid_video); . threshold ( simpleBitmap . bitmapData , simpleBitmap. bitmapData. limite (simpleBitmap. bitmapData, ( 0 , 0 , simpleBitmap . bitmapData . width , simpleBitmap . bitmapData . height ) , new Rectangle (0, 0, simpleBitmap. bitmapData. largura, simpleBitmap. bitmapData. altura), ( 0 , 0 ) , novo ponto (0, 0), "==" 0x00000000, 0x00000000, 0x00ffffff, ; true); } ); |
, visualizzata nello stage tramite l'oggetto Bitmap simpleBitmap . Linha cópia 3 (cada ENTER_FRAME ) de conteúdo de vídeo em nosso BitmapData , exibido no Palco usando o objeto Bitmap simpleBitmap . il metodo threshold() , nelle modalità descritte in precedenza. Linha 4 aplica-se (sempre em cada ENTER_FRAME ) no nosso BitmapData método threshold() , da maneira descrita anteriormente. eseguendo l'operazione di uguaglianza "==" . Neste exemplo, utilizados os parâmetros que se aplicam threshold sobre toda a área do Bitmap de realizar a operação de igualdade "==" . in dipendenza della maschera) viene sostituito con il vuoto 0x00000000 . Se o leito é igual aos pixels pretos 0x00000000 (ou 0xFF000000 na dependência da máscara) é substituído com o vazio 0x00000000 . No final, portanto, temos um chroma key no preto.
Utilizando um intervalo
Esta técnica é muito bem quando você quer substituir a cor é preciso. Em nosso exemplo anterior, na verdade, um valor de 0x00000001 não é levado em consideração. Para superar esse obstáculo, devemos fazer algo diferente de "==" . Além disso, em um filme real, há sombras e reflexos a considerar que, na prática, que se deslocam a nossa cor chroma de um nível mínimo para um nível máximo. O ideal, então, seria a de criar uma série de filtros de threshold que ocorrem tanto um nível escuro que um nível de luz da cor que escolheu para a croma.
Para conseguir isso não é o suficiente para escrever:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Event . ENTER_FRAME , addEventListener ( Evento . ENTER_FRAME, e : Event ) : void { function (e: Evento ): void { . draw ( vid_video ) ; .. simpleBitmap bitmapData empate (vid_video); . threshold ( simpleBitmap . bitmapData , simpleBitmap. bitmapData. limite (simpleBitmap. bitmapData, ( 0 , 0 , simpleBitmap . bitmapData . width , simpleBitmap . bitmapData . height ) , new Rectangle (0, 0, simpleBitmap. bitmapData. largura, simpleBitmap. bitmapData. altura), ( 0 , 0 ) , novo ponto (0, 0), "<=", 0x00222222, 0x00000000, 0x00ffffff, ; true); } ); |
. O resultado, embora apreciável, não é correto, por uma razão simples: usando o operador "<=" , que é conceitualmente correto, confrontanto todos os níveis inferior ou igual a 0x00222222 . Segue-se que o valor 0x00002200 - o que é um verde escuro - será considerado como chroma, que não era a nossa intenção, querendo filtrar apenas a gradação preto e alguns um pouco 'mais claro, mas sempre a "negra". le tre componenti RGB separatamente. A técnica mais preciso é o parâmetro para explorar mask e analisar através do threshold dos três componentes RGB separadamente. O que vamos conseguir agora é um filtro inverso, ou seja, vamos criar uma máscara que irá conter apenas a nossa gama. Primeiro vamos criar uma função que pode operar o controle sobre um canal RGB específico:
1 2 3 4 5 6 7 8 9 10 11 | myBitmapData : BitmapData , channel : String , op : String , threshold : uint ) : void { applyThresholdRGB função (myBitmapData: BitmapData , canal: Cordas , op: Cordas , limite: uint ): void { uint = ( channel == "red" ) ? 0x00FF0000 : ( ( channel == "green" ) ? 0x0000FF00 : 0x000000FF ) ; var MaskColor: uint = (canal == "vermelho") 0x00FF0000: ((canal == "verde") 0x0000FF00:? 0x000000FF)?; ( myBitmapData , myBitmapData. limite (myBitmapData, ( 0 , 0 , myBitmapData . width , myBitmapData . height ) , new Rectangle (0, 0, myBitmapData. largura, myBitmapData. altura), ( 0 , 0 ) , novo ponto (0, 0), op, limiar 0x00000000, MaskColor, ; false); } |
) su un canale RGB specificato nel parametro channel . A função applyThresholdRGB() permite que você execute um dado de comparação (ver parâmetro op ) em um canal RGB especificado no parâmetro de channel . Vamos criar uma função que gera uma máscara:
1 2 3 4 5 6 7 8 9 10 11 12 13 | myBitmapData : BitmapData , colorLow : uint , colorHi : uint ) : void { createBitmapMask função (myBitmapData: BitmapData , colorLow: uint , colorHi: uint ): void { / / Red "red" , "<" , colorLow ) ; applyThresholdRGB (myBitmapData, "vermelho", "<", colorLow); "red" , ">" , colorHi ) ; applyThresholdRGB (myBitmapData, "vermelho", ">", colorHi); / / Verde "green" , "<" , colorLow ) ; applyThresholdRGB (myBitmapData, "verde", "<", colorLow); "green" , ">" , colorHi ) ; applyThresholdRGB (myBitmapData, "verde", ">", colorHi); / / Azul "blue" , "<" , colorLow ) ; applyThresholdRGB (myBitmapData, "azul", "<", colorLow); "blue" , ">" , colorHi ) ; applyThresholdRGB (myBitmapData, "azul", ">", colorHi); } |
Agora que temos a máscara (no exemplo é a caixa no canto superior direito máscara de bitmap), podemos usá-lo para sobrepor a imagem original, eliminando as partes que não são necessários. Em resumo, temos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Event . ENTER_FRAME , addEventListener ( Evento . ENTER_FRAME, e : Event ) : void { function (e: Evento ): void { / / Clonar a imagem de vídeo . draw ( vid_video ) ; .. simpleBitmap bitmapData empate (vid_video); / / Cria um objeto com bitmap dados BitmapData mesmo que o original Bitmap = new Bitmap ( simpleBitmap . bitmapData . clone ( ) ) ; var bitmapMask: Bitmap = new Bitmap (. simpleBitmap. bitmapData clone ()); / / Cria a máscara bitmapData , 0x00000000 , 0x00222222 ) ; createBitmapMask (bitmapMask. bitmapData, 0x00000000, 0x00222222); / / I aplicar a máscara para o original em BlendMode.ERASE . draw ( bitmapMask , null , null , BlendMode . ERASE , null , false ) ; .. simpleBitmap bitmapData empate (bitmapMask, null, null, BlendMode ERASE, null, false.); } ); |
O resultado final é visível na caixa no canto inferior direito Mesclar Bitmap. Desta forma é possível aplicar o Chroma Key não a uma cor específica, mas a uma escala.










Obrigado!
@ Imagineflash: por favor
você pode fazer o upload. fla que você criou?
E no caso de você precisava de um limbo verde (ou branco) em um estúdio de filme em que atirar em um muito, muito baixo ... Líquido Gate Studio,
Muito bom exemplo -, gostaria de ver o Fla também.!
@ Kevin: Ver https://github.com/gfazioli/Chroma-Key
@ Ale: Como mostrado @ Kevin ver em GitHub repo: https://github.com/gfazioli/Chroma-Key