更改Android应用程序中对象的颜色

时间:2015-06-22 06:03:21

标签: android opencv image-processing edge-detection

基本上我的目标是实时改变油漆应用的物体颜色。为了实现这一目标,我遵循以下概念:

  1. 我使用canny()方法查找对象。
  2. 使用findContours()进行边缘检测。
  3. 使用drawContours()为对象着色。
  4. 如果有任何其他概念需要达到目标,请     建议我。我试过但没有得到精确的轮廓边缘。

    原始输入:

    original image

    预期输出:

    Expected output

    当前输出:

    getting output

      

    我正在以灰度显示图像,但我想以rgb模式。

    这是我的代码:

    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 个答案:

答案 0 :(得分:1)

我相信您将灰度图像移动到彩色图像时出错了。

尝试: Imgproc.cvtColor(mRgba, mIntermediateMat, Imgproc.COLOR_YUV2RGBA_NV21, 4); 代替: Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);

答案 1 :(得分:1)

派对有点晚了。我没有尝试过代码,但我怀疑:

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

即使mIntermediateMat在这里是8位4通道垫,

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

这里变成了8位1通道垫。参考:canny doc

  

输出边缘图;它与图像具有相同的大小和类型。

结果,

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

gaussian_output是一个8位1通道垫,并且......

return gaussian_output;

返回8位1通道(灰度)图像。

答案 2 :(得分:0)

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

您应该使用LIBPNG进行图像处理。使用它,您可以通过设置颜色矩阵将其转换为灰度或彩色图像。