Android使用OpenCV 4.5.0实现扑克牌识别(源码分享)

一、显示效果展示

二、OpenCV 4.5.0

OpenCV 4.5.0是OpenCV(Open Source Computer Vision Library,开源计算机视觉库)的一个重要更新版本,该版本在多个方面进行了优化和新增了多项功能。

三、ONNX模型

ONNX(Open Neural Network Exchange)模型是一种针对机器学习所设计的开放式的文件格式,用于存储训练好的模型。它允许不同的深度学习框架(如PyTorch、TensorFlow、MXNet等)之间交换和共享模型,使得模型可以在不同平台和工具上进行部署和推理。

四、OpenCV加载onnx模型进行前向推理实现识别扑克牌识别

java 复制代码
    //统计预测的结果
    private int[] number_class=new int[54];
    public Bitmap detection(Bitmap bp){
        Canvas can=new Canvas();
        Paint p=new Paint();
        android.graphics.Bitmap.Config bitmapConfig = bp.getConfig();
        bp = bp.copy(bitmapConfig, true);
        can=new Canvas(bp);
        p.setAntiAlias(true);
        //不填充,默认填充
        p.setStyle(Paint.Style.STROKE);
        //设置线条宽度
        p.setStrokeWidth(5);
        //设置颜色
        p.setColor(0xFF33FFFF);
        p.setTextAlign(Paint.Align.LEFT);
        p.setTextSize(50);

        Mat blob = Dnn.blobFromImage(src, IN_SCALE_FACTOR,
                new Size(IN_WIDTH, IN_HEIGHT),
                new Scalar(MEAN_VAL, MEAN_VAL, MEAN_VAL), false);
        net.setInput(blob);
        blob.release();

        //获取输出层的名字
        List<String> outnames=net.getUnconnectedOutLayersNames();
//        Log.i("aa",String.valueOf(outnames));
        //创建输出矩阵集合
        List<Mat> detections = new ArrayList<Mat>();
        net.forward(detections,outnames);
        //获取输出的盒子和置信度
        Mat scores=detections.get(0);
        Mat boxes= detections.get(1);
        scores= scores.reshape(1,3000).colRange(1,55);
        boxes= boxes.reshape(1,3000);
        Size ss=scores.size();
//        Log.i("aa",String.valueOf(scores));
//        Log.i("aa",String.valueOf(boxes));

        List<Rect2d> rect2dList=new ArrayList<>();//box信息
        List<Float> confList=new ArrayList<>();//置信度
        List<Integer> objIndexList=new ArrayList<>();//对象类别索引


        for(int i=0; i<scores.rows();i++){
            Mat one_row=scores.rowRange(i,i+1);
            Core.MinMaxLocResult max_index=Core.minMaxLoc(one_row);
            double max_value=max_index.maxVal;
            Point location=max_index.maxLoc;
            if(max_value>0.4){

                confList.add((float) max_value);
                objIndexList.add((int)location.x);

                Mat box_one=boxes.rowRange(i,i+1);
                float[] aa=new float[4];
                box_one.get(0,0,aa);

                double x1=aa[0];
                double y1=aa[1];
                double x2=aa[2];
                double y2=aa[3];
                rect2dList.add(new Rect2d(x1,y1,x2,y2));

            }

        }

        //去重
        //去重后的索引值
        MatOfInt index=new MatOfInt();
        //转换box的结果集
        MatOfRect2d boxe=new MatOfRect2d(rect2dList.toArray(new Rect2d[0]));
        //转换置信度结果集
        float[] confArr=new float[confList.size()];
        for(int j=0;j<confList.size();j++){
            confArr[j]=confList.get(j);
        }
        MatOfFloat con=new MatOfFloat(confArr);
        //使用nms去重
        Dnn.NMSBoxes(boxe,con,0.4f,0.45f,index);
        if (index.empty()){
            return bp;
        }
        //画框
        int[] ints=index.toArray();

        for(int x:ints){
//            Log.i("aa",String.valueOf(x));

            double[] aa=new double[4];
            boxe.get(x,0,aa);
            //Log.i("aa",String.valueOf(aa[0]));
            //Imgproc.rectangle(src,new Point(aa[0]*src.width(),aa[1]*src.height()-70),new Point(aa[2]*src.width()+200,aa[1]*src.height()),new Scalar(255,255,255),-1);
            //Imgproc.rectangle(src,new Point(aa[0]*src.width(),aa[1]*src.height()),new Point(aa[2]*src.width(),aa[3]*src.height()),new Scalar(255,255,0),10);

            //Imgproc.putText(src,""+classNames[objIndexList.get(x)]+":"+confList.get(x),new Point(aa[0]*src.width(),aa[1]*src.height()),Imgproc.FONT_HERSHEY_SIMPLEX, 3, new Scalar(0, 0, 0));
            //画框
            can.drawRect((float) aa[0]*src.width(),(float) aa[1]*src.height(),(float)aa[2]*src.width(),(float)aa[3]*src.height(),p);
            //绘制填充框
            p.setStyle(Paint.Style.FILL);
            p.setColor(0xFFFFCC00);
            can.drawRect((float) aa[0]*src.width(),(float) aa[1]*src.height()-60,(float)aa[2]*src.width()+150,(float)aa[1]*src.height(),p);
            //写字
            p.setColor(0xFFFF0000);
            can.drawText(classNames[objIndexList.get(x)]+": "+String.format("%.3f", confList.get(x)),(float)aa[0]*src.width(),(float) aa[1]*src.height()-10,p);
            p.setStyle(Paint.Style.STROKE);
            p.setColor(0xFF33FFFF);

            //统计类别信息
            number_class[objIndexList.get(x)]+=1;
        }

五、完整源码下载:

Card.zip: https://url83.ctfile.com/f/45573183-1373015108-43a4dd?p=7526 (访问密码: 7526)

相关推荐
Jinkxs2 分钟前
告别“测试滞后”:AI实时测试工具在敏捷开发中的落地经验
人工智能·测试工具·敏捷流程
七元权3 分钟前
论文阅读-Gated CRF Loss for Weakly Supervised Semantic Image Segmentation
论文阅读·深度学习·计算机视觉·语义分割·弱监督
John_ToDebug24 分钟前
大模型提示词(Prompt)终极指南:从原理到实战,让AI输出质量提升300%
人工智能·chatgpt·prompt
居然JuRan24 分钟前
LangGraph从0到1:开启大模型开发新征程
人工智能
双向3333 分钟前
实战测试:多模态AI在文档解析、图表分析中的准确率对比
人工智能
用户51914958484535 分钟前
1989年的模糊测试技术如何在2018年仍发现Linux漏洞
人工智能·aigc
人类发明了工具36 分钟前
【深度学习-基础知识】单机多卡和多机多卡训练
人工智能·深度学习
用户5191495848451 小时前
检索增强生成(RAG)入门指南:构建知识库与LLM协同系统
人工智能·aigc
CoovallyAIHub1 小时前
方案 | 动车底部零部件检测实时流水线检测算法改进
深度学习·算法·计算机视觉
CoovallyAIHub1 小时前
方案 | 光伏清洁机器人系统详细技术实施方案
深度学习·算法·计算机视觉