Apply cartoon filter: Android

cartoon_filter
How would you apply cartoon filter to an image? Photoshop. No I mean programmatically on fly! OpenCV is powerful and rich. It has extensive applications on computer vision.

OpenCV is available for android. Refer official documentation site for setting up and creating OpenCV based project.

We will try to reduce the number of colors used in image to give “flat” look. We will use the mean shift to reduce the number for damping pixels. In simpler term, mean shift will replace pixels with mean value within range of distance/radius. The theory is better explained here in stackoverflow. I came to know about this technique from this blog, it helped me a lot.

I hope you have setup the OpenCV library and project successfully. OpenCV uses Mat to represent pixel values in simple terms. We would need to convert android bitmap to Mat. OpenCV provides solid filter algorithm for mean shift segmentation. Lets create a CartoonFilter class that will process our image pixels.

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

public class CartoonFilter {

	float sp;
	float sr;
	  
	Mat gray, edges;
	Mat hsv;
	  
	Mat bgr, img0;
	Mat edgesBgr;
	
	public CartoonFilter(){
		gray = new Mat();
		edges = new Mat();
		hsv = new Mat();
		bgr = new Mat();
		img0 = new Mat();
		edgesBgr = new Mat();
		
		sp = Math.max(1, Math.max(1, 15));
		sr = Math.max(1, Math.max(1, 40));
	}
	
	public void changeCartoonParameter(float spMax, float srMax){
		sp = Math.max(1, Math.max(1, spMax));
		sr = Math.max(1, Math.max(1, srMax));
	}

	boolean processFrame(Mat inputFrame, Mat outputFrame)
	{
		Imgproc.cvtColor(inputFrame, bgr, Imgproc.COLOR_BGRA2BGR);
		Imgproc.pyrMeanShiftFiltering(bgr.clone(), bgr, sp, sr);
		
		getGray(bgr, gray);
		Imgproc.Canny(gray, edges, 150, 150);
		
		Imgproc.cvtColor(edges, edgesBgr, Imgproc.COLOR_GRAY2BGR);
		
		//bgr = bgr - edgesBgr;
		Core.subtract(bgr, edgesBgr, bgr);
		
		Imgproc.cvtColor(bgr, outputFrame, Imgproc.COLOR_BGR2BGRA);
		return true;
	}
	
	void getGray(Mat input, Mat gray){
		int numChannes = input.channels();
		  
		if (numChannes == 4){
			Imgproc.cvtColor(input, gray, Imgproc.COLOR_BGRA2GRAY);
		    
		}
		else if (numChannes == 3)
		{
			Imgproc.cvtColor(input, gray, Imgproc.COLOR_BGR2GRAY);
		}
		else if (numChannes == 1)
		{
		    gray = input;
		}
	}
	
}

Our implementation would look like this.

public class MainActivity extends Activity implements OnSeekBarChangeListener{

	String TAG = "CARTOON";
	private ImageView cartoonView;
	private SeekBar bar;
	
	Bitmap cartoonBMP;
	CartoonFilter cf;
	
	Mat output;
	Mat imgMat;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		setContentView(R.layout.activity_main);
		
		cartoonView = (ImageView)findViewById(R.id.cartoonImg);
	}
	
	@Override
    public void onPause()
    {
        super.onPause();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
    }
    
    private void init(){        
        imgMat = new Mat();
        output = new Mat();
        
        try {
			imgMat = Utils.loadResource(getBaseContext(), R.drawable.duck);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        
        cf= new CartoonFilter();
        cf.processFrame(imgMat, output);        
        
        Bitmap tmp = Bitmap.createBitmap(output.cols(), output.rows(), Bitmap.Config.ARGB_8888);               
        Utils.matToBitmap(output, tmp);
        
        
        cartoonView.setImageBitmap(tmp);
    }
    
    private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                    init();
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };
}

2 Comments

  • where is code??

  • can you provide the full code

Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>