Changing the color of an object in an Android application

4.5k views Asked by At

Basically my goal is change the color of object in real time for paint application. To achieve this goal I follow the following concepts:

  1. I have used the canny() method for finding the object.
  2. Using findContours() for edge detection.
  3. using drawContours() for coloring the object.

If there is any other concept required to achieve the goal please suggest to me. I have tried but not getting exact contours edge.

Original input:

original image

Expected output:

Expected output

Current output:

getting output

I am getting image in gray scale but i want in rgb mode.

here is my code:

package com.example.imageprocess;

import java.util.ArrayList;
import java.util.List;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;

public class MainActivity extends Activity implements CvCameraViewListener2 {

        private Mat                    mRgba;
        private Mat                    mIntermediateMat;
        private Mat                    mGray;

        private CameraBridgeViewBase   mOpenCvCameraView;

        private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                    case LoaderCallbackInterface.SUCCESS:
                    {
                        Log.i("OPENCVACTIVITY", "OpenCV loaded successfully");

                        // Load native library after(!) OpenCV initialization
                       // System.loadLibrary("mixed_sample");

                        mOpenCvCameraView.enableView();
                    } break;
                    default:
                    {
                        super.onManagerConnected(status);
                    } break;
                }
            }
        };

       /* public MainActivity() {
            Log.i("OPENCVACTIVITY", "Instantiated new " + this.getClass());
        }
*/
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
          getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

            setContentView(R.layout.activity_main);

            mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial2_activity_surface_view);
            mOpenCvCameraView.setCvCameraViewListener(this);
    }



    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);
    }

    public void onDestroy() {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onCameraViewStarted(int width, int height) {
        // TODO Auto-generated method stub
         mRgba = new Mat(height, width, CvType.CV_8UC4);
            mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);
            mGray = new Mat(height, width, CvType.CV_8UC1);

    }

    @Override
    public void onCameraViewStopped() {
         mRgba.release();
            mGray.release();
            mIntermediateMat.release();

    }

    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        Mat gaussian_output = new Mat();
         mRgba = inputFrame.rgba();
         Imgproc.Canny(inputFrame.gray(), mIntermediateMat, 80, 100);
         Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);
         Imgproc.GaussianBlur(mIntermediateMat, gaussian_output, new Size(5, 5), 5);
         List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
         Imgproc.findContours( gaussian_output, contours, new Mat(),Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0,0) );
         Scalar color = new Scalar(165, 30, 215);
        // Imgproc.drawContours(gaussian_output, contours, -1, color, 3);
         Mat hierarchy = new Mat();
      // find contours:
      Imgproc.findContours(gaussian_output, contours, hierarchy, Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE);
      for (int contourIdx = 0; contourIdx < contours.size(); contourIdx++) {
          Imgproc.drawContours(gaussian_output, contours, contourIdx,color, -1);
      }

        return gaussian_output;
    }


}
3

There are 3 answers

8
AudioBubble On

I believe that you made the error of moving the grayscale image to the coloured image.

Try: Imgproc.cvtColor(mRgba, mIntermediateMat, Imgproc.COLOR_YUV2RGBA_NV21, 4); Instead of: Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);

0
PRATEEK BHARDWAJ On

http://www.labbookpages.co.uk/software/imgProc/libPNG.html

You should use LIBPNG for image processing. Using it you can convert it to grayscale or colored image by setting color matrix.

0
pandamakes On

A bit late to the party. I have not tried the code out, but I suspect:

mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);

Even though mIntermediateMat is 8bit 4 channel mat here,

Imgproc.Canny(inputFrame.gray(), mIntermediateMat, 80, 100);

It was turned into a 8bit 1 channel mat here. ref: canny doc.

output edge map; it has the same size and type as image .

As a result,

Imgproc.GaussianBlur(mIntermediateMat, gaussian_output, new Size(5, 5), 5);

gaussian_output is an 8bit 1 channel mat, and...

return gaussian_output;

returns an 8 bit 1 channel (grayscale) image.