Open CV 3.4基础API使用

本文深入探讨了多种图像处理技术,包括人脸识别、边缘检测、模板匹配等,并提供了详细的实现方法及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    /**
     * 人脸识别
     * @throws IOException
     */
    private CascadeClassifier faceDetector;

    private void initFaceDetector() throws IOException{
        InputStream input = getResources().openRawResource(R.raw.haarcascade_upperbody);
        File cascadeDir = this.getDir("cascade", Context.MODE_PRIVATE);
        File file = new File(cascadeDir.getAbsoluteFile(),"haarcascade_upperbody.xml");
        FileOutputStream output = new FileOutputStream(file);
        byte[] buff = new byte[1024];
        int len = 0;
        while ((len = input.read(buff))!= -1){
            output.write(buff,0,len);
        }
        input.close();
        output.close();
        faceDetector = new CascadeClassifier(file.getAbsolutePath());
    }

    /**
     * 人脸识别
     * @param detector
     */
    private void faceDetect(CascadeClassifier detector){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,dst,Imgproc.COLOR_BGRA2GRAY);
        MatOfRect faces = new MatOfRect();
        detector.detectMultiScale(dst,faces,1.1,15,0,new Size(50,50),new Size());
        List<Rect> faceList = faces.toList();
        if (faceList.size() >0){
            for (Rect rect:faceList){
                Imgproc.rectangle(src,rect.tl(),rect.br(),new Scalar(255,0,0,255),2,8,0);
            }
        }
        Utils.matToBitmap(src,temp);
        src.release();
        dst.release();
        mImageView.setImageBitmap(temp);

    }

    /**
     * 对象测量
     */
    private void measureObjects(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);
        int t = 100;
        Imgproc.Canny(src,dst,t,t*2,3,false);
        List<MatOfPoint> contours = new ArrayList<>();
        Mat hierarchy = new Mat();
        Imgproc.findContours(dst,contours,hierarchy,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE,new Point(0,0));
        Imgproc.cvtColor(src,src,Imgproc.COLOR_GRAY2BGR);

        double[][] result = new double[contours.size()][2];
        for(int i = 0;i <contours.size();i++){
            Moments moments = Imgproc.moments(contours.get(i),false);
            double m00 = moments.get_m00();
            double m10 = moments.get_m10();
            double m01 = moments.get_m01();
            double x0 = m10 /m00;
            double y0 = m01 /m00;

            double arclength = Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()),true);
            double area = Imgproc.contourArea(contours.get(i));
            result[i][0] = arclength;
            result[i][1] = area;
            Log.d("liubin11 i = ",""+i);
            Log.d("liubin11 arclength = ",""+arclength);
            Log.d("liubin11 area = ",""+area);

            Imgproc.circle(src,new Point(x0,y0),2,new Scalar(255,0,0),2,8,0);
        }
        Utils.matToBitmap(src,temp);
        src.release();
        dst.release();
        hierarchy.release();

        mImageView.setImageBitmap(temp);


    }

    /**
     * 轮廓发现
     */
    private void findAndDrawContours(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);


        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);
        int t = 90;
        Imgproc.Canny(src,dst,t,t*2,3,false);
        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Mat hierarchy = new Mat();
        Imgproc.findContours(dst,contours,hierarchy,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE,new Point(0,0));
        Imgproc.cvtColor(src,src,Imgproc.COLOR_GRAY2BGR);
        for (int i =0;i<contours.size();i++){
            MatOfPoint points = contours.get(i);
            Imgproc.drawContours(src,contours,i,new Scalar(255,0,0),2,8,hierarchy,0,new Point(0,0));
        }
        Utils.matToBitmap(src,temp);
        src.release();
        dst.release();
        hierarchy.release();

        mImageView.setImageBitmap(temp);


    }

    /**
     * 模板匹配
     */
    private void templateMat(){
        Bitmap tpl = BitmapFactory.decodeResource(this.getResources(),R.drawable.fj);
        Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(),R.drawable.fjy);

        Mat src = new Mat();
        Mat tplMat = new Mat();
        Utils.bitmapToMat(bitmap,src);
        Utils.bitmapToMat(tpl,tplMat);
        int width = bitmap.getWidth() - tpl.getWidth() +1;
        int height = bitmap.getHeight() - tpl.getHeight() +1;
        Mat result = new Mat(width,height,CvType.CV_32FC1);//result 必须为单通道32位
        Imgproc.matchTemplate(src,tplMat,result,Imgproc.TM_CCORR_NORMED);
        Core.normalize(result,result,0,1.0,Core.NORM_MINMAX,-1);

        Core.MinMaxLocResult minMaxLocResult = Core.minMaxLoc(result);
        Point pt = minMaxLocResult.maxLoc;
        Imgproc.rectangle(src,pt,new Point(pt.x+tpl.getWidth(),pt.y + tpl.getHeight()),new Scalar(255,0,0,0),2,8,0);
        Utils.matToBitmap(src,bitmap);
        src.release();
        tplMat.release();
        result.release();

        mImageView.setImageBitmap(bitmap);

    }

    /**
     * 霍夫圆检测
     */
    private void houghCircleDet(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);
        //dp 分辨率与原来的一样  ;minDist 同心圆直接间隔为5; param1 梯度阈值(基于梯度检测的);param2 相交点为100次;minRadius 最小半径;maxRadius 最大半径
        Imgproc.HoughCircles(src,dst,Imgproc.CV_HOUGH_GRADIENT,1,5,100,50,30,150);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_GRAY2BGRA);
        double [] circleParams = new double[3];
        for (int i =0;i<dst.cols();i++){
            circleParams = dst.get(0,i);
            Point cp = new Point(circleParams[0],circleParams[1]);
            Imgproc.circle(src,cp,(int)circleParams[2],new Scalar(255,0,0,255),2,8,0);
        }
        Utils.matToBitmap(src,temp);
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }

    /**
     * 霍夫直线检测(从平面坐标到极坐标)
     */
    private void houphLinesDet(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Mat src = new Mat();
        Mat dst = new Mat();
        Mat lines = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.GaussianBlur(src,src,new Size(3,3),0,0,4);
        int t = 20;
        Imgproc.Canny(src,dst,t,t*2,3,false);

        Mat drawImage = new Mat(src.size(),src.type());
//        Imgproc.cvtColor(dst,dst,Imgproc.COLOR_GRAY2BGR);

        /*Imgproc.HoughLines(dst,lines,1,Math.PI/180.0,t);
//        Imgproc.cvtColor(dst,dst,Imgproc.COLOR_GRAY2BGR);

        double[] linep = new double[2];
        for (int i =0;i<lines.cols();i++){
            linep = lines.get(0,i);
            double rho = linep[0];
            double theta = linep[1];
            double a = Math.cos(theta);
            double b = Math.sin(theta);
            double x0 = a*rho;
            double y0 = b*rho;
            Point p1 = new Point(x0+1000*(-b),y0 + 1000*a);
            Point p2 = new Point(x0-1000*(-b),y0 - 1000*a);
            Imgproc.line(drawImage,p1,p2,new Scalar(255,0,0),2,8,0);
        }*/

        //直接得到直线
        Imgproc.HoughLinesP(dst,lines,1,Math.PI/180.0,t,15,3);
        double[] pts = new double[4];
        for (int i =0;i<lines.cols();i++){
            pts = lines.get(0,i);
            Point p1 = new Point(pts[0],pts[1]);
            Point p2 = new Point(pts[2],pts[3]);
            Imgproc.line(dst,p1,p2,new Scalar(255,0,0),2,8,0);
        }

        Utils.matToBitmap(dst,temp);
        src.release();
        dst.release();
        lines.release();

        mImageView.setImageBitmap(temp);
    }

    /**
     * canny 边缘检测
     *
     * 实际原理步骤:1、高斯模糊
     *      2、梯度计算
     *      3、非最大信号压制
     *      4、高低阈值链接
     *      5、显示
     */
    private void cannyEge(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);
        Imgproc.GaussianBlur(src,src,new Size(3,3),0,0,4);
        int t = 60;
        Imgproc.Canny(src,dst,t,t*2,3,false);//threshold 最低阈值,threshold2 最高阈值(一般是最低阈值的2-3倍)
                                                                        //L2qradient = true 比false识别精度更高
        Utils.matToBitmap(dst,temp);
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }


    /**
     * 计算图像梯度 Sobel 算子 / Scharr 算子
     */
    private void sobleGradient(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();

        Utils.bitmapToMat(temp,src);

        int type = 2;
        if(type ==1) {//x方向
            //ddepth = -1 不变  ; dx = 1 x方向求导 ;
//            Imgproc.Sobel(src, dst, -1, 1, 0);//x方向梯度(x方向1阶求导)
//            Imgproc.Sobel(src,dst,CvType.CV_16S,1,0);//x方向梯度(x方向求导)  深度为CvType.CV_16S效果比-1要清晰
            Imgproc.Scharr(src,dst,CvType.CV_16S,1,0);//Scharr算子,深度设为CvType.CV_16S,若为-1 可能不起作用,因为溢出了

            Core.convertScaleAbs(dst,dst);//求绝对值,去除负数
            Utils.matToBitmap(dst,temp);

        }else if (type ==2) {//y方向
//        Imgproc.Sobel(src,dst,-1,0,1);//y方向梯度(y方向求导)
//            Imgproc.Sobel(src,dst,CvType.CV_16S,0,1);//y方向梯度(y方向求导) 深度为CvType.CV_16S效果比-1要清晰
            Imgproc.Scharr(src,dst,CvType.CV_16S,0,1);//Scharr算子,深度设为CvType.CV_16S,若为-1 可能不起作用,因为溢出了
            Core.convertScaleAbs(dst,dst);//求绝对值,去除负数
            Utils.matToBitmap(dst,temp);

        }else {//x,y 方向梯度结合使用

            Mat xdst = new Mat();
            Mat ydst = new Mat();

//            Imgproc.Sobel(src, xdst, CvType.CV_16S, 1, 0);
//            Imgproc.Sobel(src, ydst, CvType.CV_16S, 0, 1);

            Imgproc.Scharr(src, xdst, CvType.CV_16S, 1, 0);
            Imgproc.Scharr(src, ydst, CvType.CV_16S, 0, 1);

            Core.convertScaleAbs(xdst, xdst);
            Core.convertScaleAbs(ydst, ydst);
            Mat xydst = new Mat();
            Core.addWeighted(xdst, 0.5, ydst, 0.5, 30, xydst);//x,y 方向的权重都是0.5
            Utils.matToBitmap(xydst, temp);
            xdst.release();
            ydst.release();
            xydst.release();
        }

        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }

    /**
     * 直方图均衡化
     */
    private void histogramEq(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(selectBitmap,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);//必须转为灰度图,单通道
        Imgproc.equalizeHist(src,dst);//直方图均衡化
        Utils.matToBitmap(dst,temp);

        src.release();
        dst.release();
        mImageView.setImageBitmap(selectBitmap);
    }

    /**局部阈值:
     * 自适应阈值--均值C
     * 自适应阈值--高斯C
     */

    private void adaptiveThresholdBinary(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);//转为8位灰度单通道图
        //自适应阈值
//        Imgproc.adaptiveThreshold(src,dst,255,Imgproc.ADAPTIVE_THRESH_MEAN_C,Imgproc.THRESH_BINARY,391,0.0);
        //高斯C
        Imgproc.adaptiveThreshold(src,dst,255,Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,Imgproc.THRESH_BINARY,591,0.0);


        Utils.matToBitmap(dst,temp);
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }


    /**全局阈值:
     * 阈值二值化
     * 阈值反二值化
     * 阈值截断
     * 阈值取0
     * 阈值取0反
     */
    private void thresholdImg(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);//转为8位灰度单通道图
        //thresh 为指定阈值,若此值指定则以此值为阈值,若设置为0,最后一个参数加上Imgproc.THRESH_OTSU 则自动计算阈值
//        Imgproc.threshold(src,dst,166,255,Imgproc.THRESH_BINARY);//阈值二值化
//        Imgproc.threshold(src,dst,166,255,Imgproc.THRESH_BINARY_INV);//阈值反二值化

//        Imgproc.threshold(src,dst,0,255,Imgproc.THRESH_BINARY |Imgproc.THRESH_OTSU);//自动阈值二值化
//        Imgproc.threshold(src,dst,0,255,Imgproc.THRESH_BINARY_INV |Imgproc.THRESH_OTSU);//自动阈值反二值化

//        Imgproc.threshold(src,dst,0,255,Imgproc.THRESH_TRUNC |Imgproc.THRESH_OTSU);//阈值截断
//        Imgproc.threshold(src,dst,0,255,Imgproc.THRESH_TOZERO |Imgproc.THRESH_OTSU);//阈值取0
        Imgproc.threshold(src,dst,0,255,Imgproc.THRESH_TOZERO_INV |Imgproc.THRESH_OTSU);//阈值取0反


        Utils.matToBitmap(dst,temp);
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);


    }


    /**
     * 直线识别(横线)
     */
    private void morphLineDetection(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);//转成灰度图(单通道)
        Imgproc.threshold(src,src,0,255,Imgproc.THRESH_BINARY_INV | Imgproc.THRESH_OTSU);//二值化处理
        //strElement 结构元素形态的选取,此处Imgproc.MORPH_RECT 为特殊矩形,高为1
        Mat strElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(20,1),new Point(-1,-1));
        Imgproc.morphologyEx(src,dst,Imgproc.MORPH_OPEN,strElement);//开操作


        Utils.matToBitmap(dst,temp);

        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }

    /**
     * 开(先腐蚀再膨胀),闭(先膨胀再腐蚀) 操作
     */
    private void openOrClose(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2GRAY);//转成灰度图(单通道)
        Imgproc.threshold(src,src,0,255,Imgproc.THRESH_BINARY_INV | Imgproc.THRESH_OTSU);//二值化处理
        //strElement 结构元素形态的选取
        Mat strElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(3,3),new Point(-1,-1));
//        Imgproc.morphologyEx(src,dst,Imgproc.MORPH_OPEN,strElement);//开操作
        Imgproc.morphologyEx(src,dst,Imgproc.MORPH_CLOSE,strElement);//闭操作

        Utils.matToBitmap(dst,temp);

        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }

    /**
     * 图片腐蚀(既最小值滤波)和膨胀(既最大值滤波)
     */
    private void erodeOrDilate(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        //结构形态的选取
        Mat strElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(3,3),new Point(-1,-1));
//        Imgproc.erode(src,dst,strElement,new Point(-1,-1),5);//腐蚀, 最后一个参数,表示执行几次腐蚀
        Imgproc.dilate(src,dst,strElement,new Point(-1,-1),5);//膨胀,最后一个值表示执行1次膨胀
        Utils.matToBitmap(dst,temp);

        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }

    /**
     * 自定义滤波器
     */
    private void customFilter(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);
        Mat kernel = getCustomOperator();
        Imgproc.filter2D(src,dst,-1,kernel,new Point(-1,-1),0.0,4);
        Utils.matToBitmap(dst,temp);
        kernel.release();
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);
    }

    private Mat getCustomOperator(){
        Mat kernel = new Mat(3,3,CvType.CV_32FC1);//自定义滤波算子,必须是基数 如此处的(3,3)
        kernel.put(0,0,1.0/9.0,1.0/9.0,1.0/9.0,1.0/9.0,1.0/9.0,1.0/9.0,1.0/9.0,1.0/9.0,1.0/9.0);//模糊
//        kernel.put(0,0,-1,-1,-1,-1,8,-1,-1,-1,-1);//拉普拉斯边缘
//        kernel.put(0,0,-1,-1,-1,-1,9,-1,-1,-1,-1);//拉普拉斯边缘锐化
        return kernel;
    }

    /**
     * 双边模糊
     */
    private void biBlur(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);

        Imgproc.cvtColor(src,src,Imgproc.COLOR_BGRA2BGR);//4通道转3通道,双边模糊只支持3通道,或单通道,而Bitmap是4通道的,要做转换
        Imgproc.bilateralFilter(src,dst,15,150,15,4);//双边模糊

        Mat kernel = new Mat(3,3,CvType.CV_16S);
        kernel.put(0,0,0,-1,0,-1,5,-1,0,-1,0);
        Imgproc.filter2D(dst,dst,-1,kernel,new Point(-1,-1),0,4);//锐化处理

        Utils.matToBitmap(dst,temp);
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);

    }

    /**
     * 高斯模糊 速度没有均值模糊快
     */
    private void gaussianBlur(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);

        //Size 中若不为0则以size中的计算,若为0则已sigmaX,Y来计算模糊范围

        Imgproc.GaussianBlur(src,dst,new Size(3,3),0,0,4);

        Utils.matToBitmap(dst,temp);
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);

    }

    /**
     * 均值模糊
     */
    private void meanBlur(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Mat src = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(temp,src);

        //Size 表示内核的大小(也叫算子) 都必须为正数和奇数,模糊范围如(9,9) 表示x方向9个像素,y方向9个像素,如(1,9) 表示只在y方向做模糊
        //Point (-1,-1)表示默认为内核中心点
        //最后一个参数 用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT
        Imgproc.blur(src,dst,new Size(1,35),new Point(-1,-1),4);

        Utils.matToBitmap(dst,temp);
        src.release();
        dst.release();

        mImageView.setImageBitmap(temp);

    }

    /**
     * 截取图片指定区域
     */
    private void getROIArea(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);

        Rect roi = new Rect(200,150,200,300);
        Bitmap roimap = Bitmap.createBitmap(roi.width,roi.height,Bitmap.Config.ARGB_8888);
        Mat src  = new Mat();
        Utils.bitmapToMat(temp,src);
        Mat roiMat = src.submat(roi);//截取指定位置图片
        Mat roiDstMat = new Mat();
        Imgproc.cvtColor(roiMat,roiDstMat,Imgproc.COLOR_BGR2GRAY);//转灰度图
        Utils.matToBitmap(roiDstMat,roimap);

        roiDstMat.release();
        roiMat.release();
        src.release();


        mImageView.setImageBitmap(roimap);

    }


    /**
     * 创建空白的Mat
     */
    private void creatMat(){
        Bitmap bitmap = Bitmap.createBitmap(400,600,Bitmap.Config.ARGB_8888);
//        Mat dst = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC1,new Scalar(100));//CU_8UC1 表示一个通道,所以后面的Scalar也只有一个通道
        Mat dst = new Mat(bitmap.getHeight(),bitmap.getWidth(),CvType.CV_8UC4,new Scalar(255,0,0,255));//通道顺序agbr
        Utils.matToBitmap(dst,bitmap);
        dst.release();

        mImageView.setImageBitmap(bitmap);
    }

    /**
     * 转灰度图
     */
    private void convert3Gray(){
        Mat src = new Mat();
        Mat dst = new Mat();
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Utils.bitmapToMat(temp,src);
        Imgproc.cvtColor(src,dst,Imgproc.COLOR_BGR2GRAY);
        Utils.matToBitmap(dst,temp);
        src.release();//必须释放内存
        dst.release();
        mImageView.setImageBitmap(temp);
    }

    /**
     * 利用Mat像素反转
     */
    private void invert(){
        Mat src = new Mat();
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);


        Utils.bitmapToMat(temp,src);
        //pixel options
        int width = src.cols();
        int height = src.rows();
        int cnum = src.channels();//通道数,如 ARGB_8888 占4个通道
        byte[] bgra = new byte[cnum];
        long startTime = System.currentTimeMillis();
        for (int row = 0; row <height;row++){
            for (int col = 0;col < width;col++){
                src.get(row,col,bgra);//将row行,col列的像素,保存到bgra中
                for (int i = 0;i< cnum;i++){
                    bgra[i] = (byte)(255 -bgra[i]&0xff);//0xff 使得byte 不发生有符号拓展,使用一个掩码来限制. 主要对负数的限制
                }
                src.put(row,col,bgra);
            }
        }
        long end = System.currentTimeMillis() - startTime;
        Log.d(TAG,"inver total time "+ end);
        Utils.matToBitmap(src,temp);
        src.release();

        mImageView.setImageBitmap(temp);

    }

    /**
     * 利用Mat像素反转
     */
    private void invert2(){
        Mat src = new Mat();
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Utils.bitmapToMat(temp,src);
        long startTime = System.currentTimeMillis();
        Core.bitwise_not(src,src);

        long end = System.currentTimeMillis() - startTime;
        Log.d(TAG,"invert2 total time "+ end);
        Utils.matToBitmap(src,temp);
        src.release();

        mImageView.setImageBitmap(temp);

    }

    /**
     * 像素减法
     */
    private void subStract(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Mat src = new Mat();

        Utils.bitmapToMat(temp,src);
        Mat whiteImg = new Mat(src.size(),src.type(), Scalar.all(255));//创建一个白色的Mat 大小和src必须一样
        long startTime = System.currentTimeMillis();

        Core.subtract(whiteImg,src,src);

        long end = System.currentTimeMillis() - startTime;
        Log.d(TAG,"subStract end = "+end);

        Utils.matToBitmap(src,temp);
        src.release();
        whiteImg.release();
        mImageView.setImageBitmap(temp);
    }

    /**
     * 像素加法
     */
    private void add(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Mat src = new Mat();

        Utils.bitmapToMat(temp,src);
        Mat whiteImg = new Mat(src.size(),src.type(), Scalar.all(255));//创建一个白色的Mat 大小和src必须一样
        long startTime = System.currentTimeMillis();

//        Core.add(whiteImg,src,src);
        Core.addWeighted(whiteImg,0.5,src,0.5,0,src);

        long end = System.currentTimeMillis() - startTime;
        Log.d(TAG,"subStract end = "+end);

        Utils.matToBitmap(src,temp);
        src.release();
        whiteImg.release();
        mImageView.setImageBitmap(temp);
    }

    /**
     * 调整对比度和亮度
     */
    private void adjustContrast(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        Mat src = new Mat();

        Utils.bitmapToMat(temp,src);
        src.convertTo(src, CvType.CV_32F);//转成32位的浮点数,为后面能使用浮点数计算所要做的步骤
        Mat whiteImg = new Mat(src.size(),src.type(), Scalar.all(1.25));//创建一个白色的Mat 大小和src必须一样
        Mat bwImg = new Mat(src.size(),src.type(),Scalar.all(30));
        long startTime = System.currentTimeMillis();

        Core.multiply(whiteImg,src,src);//对各像素先乘以1.25
        Core.add(bwImg,src,src);//再对各个像素加个30


        long end = System.currentTimeMillis() - startTime;
        Log.d(TAG,"subStract end = "+end);

        src.convertTo(src,CvType.CV_8U);//将src转为CV_8U,才能转为Bitmap
        Utils.matToBitmap(src,temp);
        src.release();
        whiteImg.release();
        bwImg.release();

        mImageView.setImageBitmap(temp);
    }
    /**
     * 利用Bitmap 的缓存中做像素反转
     */
    private void bitmapInvert(){
        Bitmap temp = selectBitmap.copy(selectBitmap.getConfig(),true);
        int width = temp.getWidth();
        int height = temp.getHeight();
        int [] pixels = new int[width*height];
        temp.getPixels(pixels,0,width,0,0,width,height);
        int index = 0;
        int a = 0,r = 0,g = 0,b = 0;
        long startTime = System.currentTimeMillis();
        for (int row = 0;row < height;row ++){
            index = row*width;
            for (int col = 0;col < width ;col ++){
                int pixel = pixels[index];
                a = (pixel>>24)&0xff;
                r = (pixel>>16)&0xff;
                g = (pixel>>8)&0xff;
                b = (pixel&0xff);

                r = 255 -r;//反转
                g = 255 -g;
                b = 255 -b;

                pixel = ((a&0xff)<<24) | ((r&0xff)<<16) | ((g&0xff)<<8) | (b&0xff);
                pixels[index] = pixel;
                index++;
            }
        }
        long end = System.currentTimeMillis() - startTime;
        Log.d(TAG,"bitmap getPixels end = "+ end);
        temp.setPixels(pixels,0,width,0,0,width,height);


        mImageView.setImageBitmap(temp);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值