1

I also need to find a library which allows to implement the "chroma key" effect in Java. The video contains some part in green color, which is replaced which a picture during the rendering in order to create a new video.

I am linking my question with a similar question which was already answered but with uncomplete answer (Looking for Chromakey library in Java). Could you please specify how did you do to have something up and working so quickly? I have been unsuccessful for some months fighting against the same issue.

c00kiemon5ter pointed several resources:

  • JavaCV
  • JAI (Java Advanced Imaging API)
  • Java Image Processing Cookbook

Which one did work for you?

Community
  • 1
  • 1
David R.
  • 11
  • 1
  • 3
  • 1
    `I am linking my question with a similar question which was already answered but with uncomplete answer.`. I see no such link. – Buhake Sindi Dec 14 '11 at 10:31
  • Sorry, I did not know how to link both questions. Finally I have added the link in the body. – David R. Dec 14 '11 at 10:36
  • 2
    possible duplicate of [Looking for Chromakey library in Java](http://stackoverflow.com/questions/7283861/looking-for-chromakey-library-in-java) – Aaron Digulla Dec 14 '11 at 10:40

2 Answers2

0

JavaCV contains lots of methods to process video streams.

This code should get you started: http://tech.groups.yahoo.com/group/OpenCV/message/59118 but it's probably too slow in Java. Try this approach:

Create a filter which turns all the green pixels into a mask (look for things that "select by color").

Use the mask to copy the background image into the video.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

I would like to contribute with a piece of code which gave me quite good results. I wonder if I used the classes and methods that Aaron Digulla suggested.

Please note that in this case my video has black background, that is why I am replacing the black color with the background image. I expect to obtain better results when I can edit the video to have green background, because black color is more likely to be used within the video main characters and replacing wrong pixels causes a quite awful effect.

--

package transparentvideo;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.io.File;
import javax.media.Manager;
import javax.media.Player;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class TransparentVideo
{
Player mediaPlayer;

JFrame invisibleFrame;
JFrame visibleFrame;
JLabel videoScreen;
JPanel offScreenVideo;

String backgroundImageFile="nature.jpg";

String videoFile="girl.mov";

public TransparentVideo() 
{

    invisibleFrame = new JFrame();

    invisibleFrame.setSize(400, 400);

    Container container=invisibleFrame.getContentPane();
    offScreenVideo =  getvidComp();
    offScreenVideo.setPreferredSize(container.getSize());
    offScreenVideo.setVisible(true);

    container.add(offScreenVideo);
    invisibleFrame.setVisible(true);

    visibleFrame=new JFrame();
    visibleFrame.setSize(container.getSize());
    visibleFrame.setLocationRelativeTo(null);

    videoScreen = new JLabel();

    visibleFrame.getContentPane().add(videoScreen);

    visibleFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    visibleFrame.setVisible(true);

    invisibleFrame.setVisible(false);

    try 
    {
        while(true)
        {

            if(mediaPlayer.getState()==Player.Started)
                reDraw();
            Thread.sleep(100);
        }
    } 
    catch (Exception ex)
    {
        System.out.println(ex.getMessage());
    }
}


public void reDraw()
{
      BufferedImage bi=new BufferedImage(videoScreen.getWidth(), videoScreen.getHeight(),
              BufferedImage.TYPE_INT_ARGB);

      bi.getGraphics().drawImage(new ImageIcon(backgroundImageFile).getImage(), 0 , 0 ,
              videoScreen.getWidth(), videoScreen.getHeight(), null);

      BufferedImage screenShot = createImage((JComponent) offScreenVideo, 
              new Rectangle(invisibleFrame.getBounds()));
      Image im = makeColorTransparent(new ImageIcon(screenShot).getImage(), Color.BLACK);

      bi.getGraphics().drawImage(im, 0 ,0 , videoScreen.getWidth(), videoScreen.getHeight(), null);

      videoScreen.setIcon(new ImageIcon(bi));

}



public static BufferedImage createImage(Component component, Rectangle region) 
{

    if (!component.isDisplayable()) {
        Dimension d = component.getSize();

        if (d.width == 0 || d.height == 0) {
            d = component.getPreferredSize();
            component.setSize(d);
        }

        layoutComponent(component);
    }

    BufferedImage image = new BufferedImage(region.width, region.height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = image.createGraphics();

    if (!component.isOpaque()) 
    {
        g2d.setColor(component.getBackground());
        g2d.fillRect(region.x, region.y, region.width, region.height);
    }

    g2d.translate(-region.x, -region.y);
    component.paint(g2d);
    g2d.dispose();
    return image;
}


public static void layoutComponent(Component component) 
{
    synchronized (component.getTreeLock()) 
    {
        component.doLayout();

        if (component instanceof Container) 
        {
            for (Component child : ((Container) component).getComponents()) 
            {
                layoutComponent(child);
            }
        }
    }
}


public JPanel getvidComp()
{

         Manager.setHint(Manager.LIGHTWEIGHT_RENDERER,true);

         try
         {
            mediaPlayer = Manager.createRealizedPlayer(new File(videoFile).toURL());

            mediaPlayer.realize();

            mediaPlayer.prefetch();

            JPanel video=new JPanel(new BorderLayout());
            video.add(mediaPlayer.getVisualComponent()) ;

            mediaPlayer.start();

            return video;

         }

         catch( Exception d)
         {
             return null;

         }
}



public static Image makeColorTransparent( Image im, final Color color) 
{
    ImageFilter filter = new RGBImageFilter() 
    {
          public int markerRGB = color.getRGB() | 0xFF000000;


          public final int filterRGB(int x, int y, int rgb) 
          {
                Color c=new Color(rgb);

                int red=c.getRed();
                int green=c.getGreen();
                int blue=c.getBlue();

                //if(red<140 && green<140 && blue<140)
                {
                    int alpha=Math.max(Math.max(red , green), Math.max(green, blue))*3;
                    c=new Color(red , green , blue , alpha>255 ?255 :alpha );
                }

                return c.getRGB();
            }
      }; 

    ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
    return Toolkit.getDefaultToolkit().createImage(ip);
}


public static void main(String[] args) {
    new TransparentVideo();
}

}
David R.
  • 11
  • 1
  • 3