如何给生津的功效/使用opencv4android调整位图WRT触摸事件 [英] How to give Fluid effect / resize bitmap wrt touch events using opencv4android

查看:243
本文介绍了如何给生津的功效/使用opencv4android调整位图WRT触摸事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新手与OpenCV4Android和Android NDK

I'm newbie with OpenCV4Android and Android NDK

努力实现

图像伸展相对于触摸点的图像。(把头发上的人脸和伸展它利用相应的触摸事件,如虚拟制作过应用程序的)

Stretch the image with respect to Touch Points on Image.(Putting Hair on Face and stretching it accordingly using touch events Like 'Virtual Make Over Application')

问题:当使用Java

从位图求矩阵和重新计算它们onTouchEvents实现弯曲函数的触摸事件。但图像得到扭曲和全矩阵得到倒挂。

Implemented warp function on Touch Events by getting Matrix from Bitmap and recomputing them onTouchEvents. But the Image get distorted and whole Matrix gets upside down.

如何使用OpenCV4Android实现这样的目标?

在这些所有的启示将是非常有益的。

Any enlightenment on these would be very helpful.

推荐答案

在经过大量的图像处理库中,每个人都有包扎和变形的效果,但没有人有在接触点的影响。因为其中许多建议可以实现使用OpenCV4Android或OpenGL,但他们都不是我的那杯茶这样的事情。

After going through lots of Image Processing Libraries, every one has warpping and morphing effects but none of them having effects on touch points. As many of them suggested you can achieve such things using OpenCV4Android or OpenGL but none of them is my cup of tea.

那么,到底实施包扎效果与NDK C语言。

So In the end implemented Warpping effect with NDK in C.

下面的算法应用于位图像素的触摸点。

Here's algorithm which applied to Bitmap Pixels on touch points.

#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include <math.h>
#include <malloc.h>
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

int *colorRed;
int *colorGreen;
int *colorBlue;
int *colorsP; //ÏñËØÖµ

int *colorAlpha;
int _width, _height;
jintArray imagecolors;

//²éÕÒ±í
static long SinXDivX_Table_8[(2 << 8) + 1];
double MySin(double x) {
    double absx;
    absx = x;
    if (x < 0)
        absx = -x;

WarpView它确实在接触点的包扎效果:

WarpView which does the warpping effect on Touch Points:

public class WarpView extends View {
    static {
        System.loadLibrary("Hello");
    }

    public native int[] warpPhotoFromC(int[] image, int height, int width,
            double max_dist, double orig_x, double orig_y, double cur_x,
            double cur_y);

    private static String TAG = WarpView.class.getSimpleName();

    private Bitmap mBmp;
    private int[] image;
    private int first = 0;
    private int[] colorR;
    private int[] colorG;
    private int[] colorB;
    private Bitmap newBmp;
    private boolean fg = true;
    private Context context;

    private static final int DEFAULT_PAINT_FLAGS = Paint.FILTER_BITMAP_FLAG
            | Paint.DITHER_FLAG;
    static Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);

    public static int HWPPQ = 110;
    public static int MMQFJ = 120;

    private int MODE = MMQFJ;

    // SA VIKALP
//  public ArrayList<WarpViewUndo> mArrayListWarpViewUndo;

    static GestureDetector mGestures;
    static ScaleGestureDetector mScaleGesture;

    private Matrix mMatrix = new Matrix();
    private Matrix mInverse = new Matrix();

    private float lastFocusX;
    private float lastFocusY;

    private boolean mIsMove = false;

    // EA VIKALP
    public WarpView(Context context) {
        super(context);
    }

    public WarpView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        dest = new RectF(0, 0, 0, 0);

        // SA VIKALP
//      mArrayListWarpViewUndo = new ArrayList<WarpViewUndo>();
        mScaleGesture = new ScaleGestureDetector(getContext(),
                new ScaleListener());
        mGestures = new GestureDetector(getContext(), new GestureListener());

        mMatrix.setTranslate(5, 5);
        mMatrix.invert(mInverse);
        // EA VIKALP
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // super.onDraw(canvas);
        if (fg) {
            int viewWidht = getWidth();
            int viewHeight = getHeight();
            float scale1 = (float) width / (float) viewWidht;
            float scale2 = (float) height / (float) viewHeight;
            scale = scale1 > scale2 ? scale1 : scale2;
            int xoffset = (viewWidht - (int) (width / scale)) / 2;
            int yoffset = (viewHeight - (int) (height / scale)) / 2;
            dest.set(xoffset, yoffset, (int) (width / scale) + xoffset,
                    (int) (height / scale) + yoffset);// = new RectF(xoffset,
                                                        // yoffset, (int)
                                                        // (width/scale)+xoffset,
                                                        // (int)
                                                        // (height/scale)+yoffset);
            // SA VIKALP
            canvas.drawColor(0x000000);
            canvas.concat(mMatrix);
            // canvas.drawColor(Color.TRANSPARENT);
            // canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            // EA VIKALP
            canvas.drawBitmap(mBmp, null, dest, mPaint);

        } else {
            // SA VIKALP
            canvas.drawColor(0x000000);
            canvas.concat(mMatrix);
            // canvas.drawColor(Color.TRANSPARENT);
            // canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            // EA VIKALP
            canvas.drawBitmap(newBmp, null, dest, mPaint);
        }
    }

    private double orig_x, orig_y;
    private double mou_dx, mou_dy;
    private double max_dist, max_dist_sq;
    private int width;
    private int height;
    private int count = 0;
    private double mou_dx_norm;
    private double mou_dy_norm;

    private float scale;
    private RectF dest;
    private double move_x, move_y;
    private int dist = (int) getResources().getDimension(R.dimen.max_dist);
    private int line_height = (int) getResources().getDimension(
            R.dimen.warp_line);

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // SA VIKALP
        mScaleGesture.onTouchEvent(event);
        mGestures.onTouchEvent(event);
        // EA VIKALP

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            orig_x = event.getX();
            orig_y = event.getY();
            orig_x = (orig_x - dest.left) * scale;
            orig_y = (orig_y - dest.top) * scale;

            break;
        case MotionEvent.ACTION_MOVE:
            if (!mIsMove) { // SA VIKALP ADDED LINE
                max_dist = dist * scale;// Math.hypot(mou_dx, mou_dy);
                if (event.getAction() != 1) {


                    // int m = event.getHistorySize();

                    move_x = event.getX();
                    move_y = event.getY();

                    move_x = (move_x - dest.left) * scale;
                    move_y = (move_y - dest.top) * scale;

                    // if(m > 0){
                    // int i2 = m + -1;
                    // orig_x = (event.getHistoricalX(i2) - dest.left)*scale;
                    // orig_y = (event.getHistoricalY(i2) - dest.top)*scale;
                    // }

                    if (move_x >= 0 && move_y >= 0) {
                            warpPhotoFromC(image, height, width, max_dist, orig_x,
                                    orig_y, move_x, move_y);
                        first++;

                        newBmp.setPixels(image, 0, width, 0, 0, width, height);
                        fg = false;
                    }
                }
                orig_x = move_x;
                orig_y = move_y;

            } 
            break;
        case MotionEvent.ACTION_UP:
            break;
        }
        invalidate();
        return true;
    }
    // SA VIKALP
//  public void applyWarpUndo(Bitmap bmp) {
//      setWarpBitmap(bmp);
//      Log.i(TAG, "Size : "
//              + mArrayListWarpViewUndo.size()
//              + " last size :"
//              + mArrayListWarpViewUndo.get(mArrayListWarpViewUndo.size() - 1)
//                      .getSize() + 1);
//      
//      for (int i = 0; i < mArrayListWarpViewUndo.size() - (mArrayListWarpViewUndo.get(mArrayListWarpViewUndo.size() - 1).getSize()+1); i++) {
//          if (mArrayListWarpViewUndo.get(i).getMove_x() >= 0 && mArrayListWarpViewUndo.get(i).getMove_y() >= 0) {
//              warpPhotoFromC(mArrayListWarpViewUndo.get(i).getImage(),
//                      mArrayListWarpViewUndo.get(i).getHeight(),
//                      mArrayListWarpViewUndo.get(i).getWidth(),
//                      mArrayListWarpViewUndo.get(i).getMax_dist(),
//                      mArrayListWarpViewUndo.get(i).getOrig_x(),
//                      mArrayListWarpViewUndo.get(i).getOrig_y(),
//                      mArrayListWarpViewUndo.get(i).getMove_x(),
//                      mArrayListWarpViewUndo.get(i).getMove_y());
//
//              newBmp.setPixels(mArrayListWarpViewUndo.get(i).getImage(), 0,
//                      mArrayListWarpViewUndo.get(i).getWidth(), 0, 0,
//                      mArrayListWarpViewUndo.get(i).getWidth(),
//                      mArrayListWarpViewUndo.get(i).getHeight());
//              fg = false;
//          }
//      }
////        Log.i(TAG, "Step Size "+mArrayListWarpViewUndo.size()-1);
//      mArrayListWarpViewUndo.remove(mArrayListWarpViewUndo.size()-2);
//      invalidate();
//  }
    public class ScaleListener implements OnScaleGestureListener {

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            // TODO Auto-generated method stub
            Matrix transformationMatrix = new Matrix();
            float focusX = detector.getFocusX();
            float focusY = detector.getFocusY();

            // Zoom focus is where the fingers are centered,
            transformationMatrix.postTranslate(-focusX, -focusY);

            transformationMatrix.postScale(detector.getScaleFactor(),
                    detector.getScaleFactor());

            /*
             * Adding focus shift to allow for scrolling with two pointers down.
             * Remove it to skip this functionality. This could be done in fewer
             * lines, but for clarity I do it this way here
             */
            // Edited after comment by chochim
            float focusShiftX = focusX - lastFocusX;
            float focusShiftY = focusY - lastFocusY;
            transformationMatrix.postTranslate(focusX + focusShiftX, focusY
                    + focusShiftY);
            mMatrix.postConcat(transformationMatrix);
            lastFocusX = focusX;
            lastFocusY = focusY;
            invalidate();
            return true;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            // TODO Auto-generated method stub
            lastFocusX = detector.getFocusX();
            lastFocusY = detector.getFocusY();
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            // TODO Auto-generated method stub

        }
    }

    public class GestureListener implements OnGestureListener,
            OnDoubleTapListener {

        @Override
        public boolean onDoubleTap(MotionEvent arg0) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onDoubleTapEvent(MotionEvent arg0) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent arg0) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onDown(MotionEvent e) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            // TODO Auto-generated method stub
            if (mIsMove) {
                mMatrix.postTranslate(-distanceX, -distanceY);
                invalidate();
            }
            return true;
        }

        @Override
        public void onShowPress(MotionEvent e) {
            // TODO Auto-generated method stub

        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            // TODO Auto-generated method stub
            return false;
        }
    }

    public void setMove(boolean isMove) {
        mIsMove = isMove;
    }

    // EA VIKALP

    public void setWarpBitmap(Bitmap bmp) {
        fg = true;// �置标志
        first = 0;
        mBmp = bmp;
        width = bmp.getWidth();
        height = bmp.getHeight();
        // 新建�?��Bitmap
        // SU VIKALP
        // newBmp = Bitmap.createBitmap(width, height,
        // Bitmap.Config.RGB_565);
        newBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        // EU VIKALP
        image = new int[width * height];

        mBmp.getPixels(image, 0, width, 0, 0, width, height);
        newBmp.setPixels(image, 0, width, 0, 0, width, height);
        // super.setImageBitmap(mBmp);
    }

    public void setMode(int mode) {
        this.MODE = mode;
    }

    /**
     * �?回处�好的图片
     * 
     * @return
     */
    public Bitmap getWrapBitmap() {
        return newBmp;
    }

    public void changeBitmapContrastBrightness() {
        float contrast, brightness;
        Random generator = new Random();
        contrast = generator.nextFloat();
        brightness = contrast;

        // Log.i(TAG, "changeBitmapContrastBrightness " + contrast);

        ColorMatrix cm = new ColorMatrix(new float[] { 
                0.501f, 0, 0, 0,0,// red
                0, 0, 0, 0, brightness,// green
                0, 0, 0.501f, 0, brightness,// blue
                0, 0, 0, 1, 0 // alpha
                });
        mPaint.setColorFilter(new ColorMatrixColorFilter(cm));
        invalidate();
    }
}

这篇关于如何给生津的功效/使用opencv4android调整位图WRT触摸事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆