欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

NO.2 Android Opencv 像素处理

程序员文章站 2023-12-25 18:26:39
...

零蚀


Mat像素处理

  • 从Mat中读取像素数据

    • 读取一个像素数据,这种方式就是和bitmap中的读取一个像素点的方式是一样的,将每个像素点进行处理。
        Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.mipmap.android);
        Mat src=new Mat();
        Mat dst=new Mat();
        Utils.bitmapToMat(bitmap,src);
    
        int width = src.width();
        int height = src.height();
        int channels=src.channels();
    
        byte[] bytes=new byte[channels];
        int b=0,g=0,r=0;
        for (int row = 0; row < height; row++) {
            for (int cols = 0; cols < width; cols++) {
                // 获取
                src.get(row, cols,bytes);
                b=bytes[0] & 0xff;
                g=bytes[1] & 0xff;
                r=bytes[2] & 0xff;
                // 修改
                b=255-b;
                g=255-g;
                r=255-r;
                // 设置
                bytes[0]= (byte) b;
                bytes[1]= (byte) g;
                bytes[2]= (byte) r;
                src.put(row,cols,bytes);
            }
        }
        Imgproc.cvtColor(src, dst,Imgproc.COLOR_BGRA2BGR);
        Utils.matToBitmap(dst,bitmap);
        ImageView image = findViewById(R.id.image);
        image.setImageBitmap(bitmap);
        src.release();
        dst.release();
    

    NO.2 Android Opencv 像素处理

    • 按照每一行来设置像素的信息,这里要注意,上面是
        byte[] bytes=new byte[channels*width];
        int pv=0;
        for (int row = 0; row < height; row++) {
            // 获取一行
            src.get(row,0,bytes);
            for (int cols = 0; cols < bytes.length; cols++) {
                // 获取每一个的每一个列的元素
                pv=bytes[cols] & 0xff;
                // 修改每一列的元素
                pv=255-pv;
                // 设置进一行的素组信息中
                bytes[cols]= (byte) pv;
            }
            src.put(row,0,bytes);
        }
    
    • 一次性全部读取
        Utils.bitmapToMat(bitmap,src);
        int width=src.width();
        int height=src.height();
        int channel=src.channels();
        byte[] bytes=new byte[channel*width*height];
        int pv=0;
        src.get(0,0,bytes);
        for (int i = 0; i < bytes.length; i++) {
            pv=bytes[i]&0xff;
            pv=255-pv;
            bytes[i]= (byte) pv;
        }
        src.put(0,0,bytes);
        Imgproc.cvtColor(src, dst,Imgproc.COLOR_BGRA2BGR);
    
  • 算数操作

    • 将图像拆成多个待合并的单通道图,或单通道合并成多通道图,计算均值和标准差,这个标准差主要可以根据大小判断图像的色彩波动,来判断图像的质量好坏。
        Core.split(src,list); // 通道分离,(分离成单通道图)
        Core.merge(list,src); // 通道合并
        // 计算通道均值,标准方差
        MatOfDouble average=new MatOfDouble();
        MatOfDouble variance=new MatOfDouble();
        Core.meanStdDev(src,average,variance);
        // 显示均值和方差
        Log.e("zero","average="+average.toArray()[0]);
        Log.e("zero","variance="+variance.toArray()[0]);
    

    μ=1ni=0nxi 均值\mu= \frac{1}{n} \sum_{i=0}^n x_i

    stddev=i=0n(xiμ)2n1 标准方差stddev = \sqrt{\frac{\sum^n_{i=0}{(x_i-\mu)^2}}{n-1}}

    • 我们可以根据均值设置二值图,(就是两种色彩构建的图图,只用0和255绘制)
        src.get(0,0,data);
        for (int i=0;i<data.length;i++) {
            pv = data[i] & 0xff;
            if(pv < average.toArray()[0]){
                data[i]=(byte)0;
            }else{
                data[i]=(byte)255;
            }
        }
        src.put(0,0,data);
    

    NO.2 Android Opencv 像素处理

  • 两个图像的加减乘除

    • 以加为例,给图片添加红色,这里如果想相加两个个Mat
        Utils.bitmapToMat(bitmap,src);
        // 给图片添加颜色
        Core.add(src,new Scalar(255,0,0),dst);
        Mat result=new Mat();
        Imgproc.cvtColor(dst,result,Imgproc.COLOR_BGRA2BGR);
    
        Bitmap bitmapRes=Bitmap.createBitmap(dst.width(),dst.height(),Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(result,bitmapRes);
        ImageView image = findViewById(R.id.image);
        image.setImageBitmap(bitmapRes);
    

    NO.2 Android Opencv 像素处理

    • 其他的计算的方法(加减乘除)
    add(Mat srcl, Mat src2, Mat dst)
    subtract(Mat srcl, Mat src2, Mat dst)
    multiply(Mat srcl, Mat src2, Mat dst)
    divide(Mat srcl, Mat src2, Mat dst)
    
    • 图像的权重叠加(这个和add的作用机理一致,不一样的是add相当于 1+1 , 而权限总和只能为1),让我们来看看1:1的融合样子。
        Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.mipmap.android);
        Bitmap bitmap2 = BitmapFactory.decodeResource(this.getResources(), R.mipmap.clothes);
        Mat src=new Mat();
        Mat src2 = new Mat();
    
        Utils.bitmapToMat(bitmap,src);
        Utils.bitmapToMat(bitmap2,src2);
        Mat dst=new Mat();
        /**
         * @Param src1 第一个输入的mat参数
         * @Param alpha 第一个图像所占的权重(权重满足条件是所有权重和为1 alpha + beta = 1)
         * @Param src2 第二个输入的mat参数
         * @Param beta 第二个图像所占的权重
         * @Param gamma 亮度 默认值为0
         * @Param dst 输出mat
         */
        Core.addWeighted(src,0.6,src2,0.4, 0 ,dst);
    	//        Core.add(src,src2,dst);
    
        // 给图片添加颜色
        Bitmap bitmapRes=Bitmap.createBitmap(src.width(),src.height(),Bitmap.Config.ARGB_8888);
        // 转化为bitmap
        Utils.matToBitmap(dst,bitmapRes);
        image.setImageBitmap(bitmapRes);
    

    NO.2 Android Opencv 像素处理

    • 这里要注意的一点是,合并的两张图像的规格一定要一致,不然就会发生报错,这里这个衣服和android机器人的图像都是 200 x 200 (32bit)的图像。

    • 像素操作(⚠️注意这里需要在取反前讲图像有透明度的改成没有透明度的格式,不然取反会变形,并且其他的操作,都要求两个图片格式一样)

    // 像素值取反,每个像素都255-b/g/r
    Imgproc.cvtColor(src,src2,Imgproc.COLOR_BGRA2RGB);
    Core.bitwise_not(src2,result);
    // 像素或操作
    Core.bitwise_or(src,src2,dst);
    // 像素与操作
    Core.bitwise_and(src,src2,dst);
    // 像素亦或操作
    Core.bitwise_xor(src,src2,dst);
    

    NO.2 Android Opencv 像素处理

    • 图像归一化处理(将像素归一化到 0~255之内)
    // 将像素值缩放到 0 - 255 之内
    Core.convertScaleAbs(src,dst);
    // 将像素值缩放到 90 - 140 之内
    /**
     * @Param src 表示源数据
     * @Param dst 目标数据
     * @Param alpha 归一化的最低值
     * @Param beta 归一化的最高值
     * @Param dtype 输出类型,默认-1源数据类型(NORM_MINMAX 最大最小值诡异算法)
     * @Param mark 遮罩层
     */
    // 将像素值缩放到 90 - 140 之内
    Core.normalize(src,dst,200,255,Core.NORM_MINMAX,-1,new Mat());
    

    NO.2 Android Opencv 像素处理

    • 最小与最大值归一化算法

      dst=(xminmaxmin)(betaalpha)+alphadst=(\frac{x-min}{max-min})*(beta-alpha)+alpha

      • 其实我觉得上面这个算法其实很好理解的,假设这里设置的上下值的差值设为Error(误差beta-alpha),数据里最大误差error(max-min),则我们用数据的单个像素点误差/最大误差 * 设定误差 , 就相当于把图像里的误差值,缩放到了我们设定的误差值上,然后加上我们设定的像素起始值,就是这个像素该有的缩放后的值了。

???? 前言
???? Android Opencv篇
???? NO.1 Android Opencv 初见

上一篇:

下一篇: