Android+Opencv图形的形状颜色识别

本文介绍如何使用Android与OpenCV库识别摄像头获取的图片中的形状(如矩形、三角形等),并通过HSV颜色空间进行区分,并统计不同颜色和形状的数量。挑战包括图像清晰度、形状辨识和底色处理。

视频效果:https://www.bilibili.com/video/BV1654y1G7Py
啥也不说来看效果
在这里插入图片描述
在这里插入图片描述
项目介绍:Android+Opencv来识别从摄像头获取到的图片形状和颜色并统计个数

其实这东西做出来不难,难的是稳定,难点就几个问题
1、摄像头获取出来的图片不够清晰图片的分辨率640*360,图像对比度和饱和度太低 (调节摄像头参数)
2、识别时菱形和矩形的区别在哪里 (外界矩形和面积比不同)
3、不同底色的图片识别方法不同 (黑白底色的不能用HSV颜色分割)
记住这几个难点,但这是做到后期才会发现的难点。

先从简单的搞起吧

项目步骤:
1、提取屏幕矩形区域
2、HSV颜色空间分割不同颜色的形状
3、通过计算矩形有四个角、三角形有三个角… 进行判断形状

有点懒得写了。。。。。
直接上代码吧,看看反馈再写了,想要继续看的说一声,我再接着写。
有一些代码是别人的。。


```java

public class ShapeDetect {
   
   

    public static String TAG="ShapeDetect";
    //颜色数量统计变量
    public static int Cambridge_blue_Num=0,yellow_Num=0,blue_Num=0,qing_Num=0,red_Num=0,mag_Num=0,black_Num=0;
    //白底照片图形数量统计变量
    public static int triangle_Num=0,rectangle_Num=0,rhombus_Num=0,pentagon_Num=0,circle_Num=0;
    //图形数量统计变量
    public static int san_Num=0,rect_Num=0,lin_Num=0,star_Num=0,yuan_Num=0;
    //浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7
    //暗 S、V=214,211     亮 S、V=176,160
    //浅蓝0、//黄色1、//品红2、//浅红色3、//蓝色4、//青色5、// 深红色6、//黑色7      车牌蓝底9  车牌绿底10
    public static double[][] HSV_VALUE_LOW = {
   
   
            {
   
   13,176,160},//浅蓝0  12,214,211
            {
   
   67, 176,160},//黄色1
            {
   
   130, 176,160},//品红2  暗:100, 176,160   亮:130,176,160
            {
   
   126,176,160},//浅红色3
            {
   
   0, 176,160},//蓝色4
            {
   
   30, 176,160},//青色5   35
            {
   
   103,176,160},// 深红色6
            {
   
   0,0,0},//黑色7   暗:0,187,0   亮:0,0,0
            {
   
   0,0,192},//标准蓝8
            {
   
   0,150,190},//车牌蓝底9      暗的TFT:0,190,190   亮的:0,180,190
            {
   
   22,104,161}//车牌绿底10    暗的TFT H:21 S要调高一点:210  V:211  亮的TFT S值要调底一点:110    10,100,148
    };

    public static double[][] HSV_VALUE_HIGH = {
   
   
            {
   
   30,255,255},//浅蓝0
            {
   
   111, 255,255},//黄色1
            {
   
   241, 255, 255.0},//品红2
            {
   
   150,255, 255},//浅红色3
            {
   
   12, 255, 255},//蓝色4
            {
   
   70, 255.0, 255},//青色5   90
            {
   
   150,255,255},// 深红色6
            {
   
   255,255,150},//黑色7   暗:28,255,184    亮:255,255,150
            {
   
   45,238,255},//标准蓝8
            {
   
   126,255,255},//车牌蓝底9   亮暗一样
            {
   
   120,255,255}//车牌绿底10   暗H:66     亮H:83
    };

    // 转换工具
    public static Mat BitmapToMat(Bitmap bmp) {
   
   
        Mat mat = new Mat(bmp.getHeight(), bmp.getWidth(), CvType.CV_8UC4);
        Utils.bitmapToMat(bmp, mat);
        return mat;
    }

    public int[] shapeDetcte(Bitmap bmp){
   
   

        Cambridge_blue_Num=0;yellow_Num=0;blue_Num=0;qing_Num=0;red_Num=0;mag_Num=0;black_Num=0;
        triangle_Num=0;rectangle_Num=0;rhombus_Num=0;pentagon_Num=0;circle_Num=0;
        san_Num=0;rect_Num=0;lin_Num=0;star_Num=0;yuan_Num=0;
        Max_area=0;//最大面积查找之后要清零
        Max_area_Yanse="品红色";//参数复位
        Max_area_shape="triangle";//参数复位

        boolean black_white_Flag=false;//false为黑白底(默认黑白底)  true为白底

        Mat mRgba=BitmapToMat(bmp);
//        save_pic(mRgba,1);
//        Mat mRgba=read_pic(false,"plate1.jpg",1);
        Mat gray=new Mat();
        Imgproc.cvtColor(mRgba,gray,Imgproc.COLOR_BGR2GRAY);//灰度化

        Mat binary=new Mat();
        Imgproc.Canny(gray,binary,50,150);//二值化  边缘检测

        Mat kernel=Imgproc.getStructuringElement(Imgproc.MORPH_RECT,new Size(3,3));//  指定腐蚀膨胀核
        Imgproc.dilate(binary,binary,kernel);

        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Mat hierarchy=new Mat();
        Imgproc.findContours(binary, contours, hierarchy,
                Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE);//查找轮廓

        double maxArea = 0;
        Iterator<MatOfPoint> each = contours.iterator();
        while (each.hasNext()) {
   
   
            MatOfPoint wrapper = each.next();
            double area = Imgproc.contourArea(wrapper);
            if (area > maxArea) {
   
   
                maxArea = area;
            }
        }

        Mat result=null;
        each = contours.iterator();
        while (each.hasNext()) {
   
   
            MatOfPoint contour = each.next();
            double area = Imgproc.contourArea(contour);
            if (area > 0.01 * maxArea) {
   
   
                // 多边形逼近 会使原图放大4倍
                Core.multiply(contour, new Scalar(4, 4), contour);
                MatOfPoint2f newcoutour = new MatOfPoint2f(contour.toArray());
                MatOfPoint2f resultcoutour = new MatOfPoint2f();
                double length = Imgproc.arcLength(newcoutour, true);
                Double epsilon = 0.01 * length;
                Imgproc.approxPolyDP(newcoutour, resultcoutour, epsilon, true);
                contour = new MatOfPoint(resultcoutour.toArray());
                // 进行修正,缩小4倍改变联通区域大小
                MatOfPoint new_contour=new MatOfPoint();
                new_contour=ChangeSize(contour);
                double new_area = Imgproc.contourArea(new_contour);//轮廓的面积
                // 求取中心点
                Moments mm = Imgproc.moments(contour);
                int center_x = (int) (mm.get_m10() / (mm.get_m00()));
                int center_y = (int) (mm.get_m01() / (mm.get_m00()));
                Point center = new Point(center_x, center_y);

                //最小外接矩形
                Rect rect = Imgproc.boundingRect(new_contour);
                double rectarea = rect.area();//最小外接矩形面积
                //轮廓的面积/最小外接矩形面积(一个圆和一个圆的外接矩形)  一定小于1 一般为0.1 0.2
                if (Math.abs((new_area/rectarea)-1)<0.2){
   
   
                    double wh = rect.size().width / rect.size().height;//宽高比值

                    if (Math.abs(wh - 1.7) < 0.7 && rect.width > 250) {
   
   

                        Mat imgSource=mRgba.clone();
                        // 绘制外接矩形
                        Imgproc.rectangle(imgSource, rect.tl(), rect.br(),
                                new Scalar(0, 0, 255), 2);
                        //*****图片裁剪***可以封装成函数*****************
                        rect.x+=5;
                        rect.width-=25;
                        rect.y+=2;// 10
                        rect.height-=3; //12
                        result=new Mat(imgSource,rect);

                        Mat black_while=result.clone();//剪切后的图片复制一份
                        Mat black_while_gray=new Mat();//存储剪切后的图片灰度化
                        Imgproc.cvtColor(black_while,black_while_gray,Imgproc.COLOR_BGR2GRAY);//灰度化图片

                        Mat hsv_gray_mask=new Mat();//存储二值化后的图片
                        Imgproc.threshold(black_while_gray,hsv_gray_mask,50,255,Imgproc.THRESH_BINARY
Android OpenCV形状识别是通过使用OpenCV库来对从摄像头获取到的图片进行处理和分析,以识别出图片中的不同形状。该项目主要包括以下步骤: 1. 提取屏幕矩形区域:通过摄像头获取图片,并提取出感兴趣的矩形区域,减少后续处理的范围。 2. HSV颜色空间分割:将图片转换到HSV颜色空间,并根据颜色的不同,将图像分割为不同的区域。 3. 形状判断:通过计算图像中各个区域的角点数目来判断形状,例如四个角表示矩形,三个角表示三角形等。 然而,在实际开发过程中,可能会遇到一些难点。其中包括: 1. 摄像头获取的图片可能不够清晰,分辨率低,对比度和饱和度也可能较低。这需要调节摄像头参数来改善图片质量。 2. 菱形和矩形之间的区别可能不太明显,需要根据外界矩形和面积比来进行区分。 3. 不同底色的图片可能需要采用不同的识别方法,比如黑白底色的图片可能不能使用HSV颜色分割。 以上是Android OpenCV形状识别的一般流程和一些可能遇到的难点。通过对摄像头获取的图片进行处理和分析,该项目可以识别出图片中的不同形状。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Android+Opencv图形形状颜色识别](https://blog.youkuaiyun.com/chenyouledashen/article/details/118067143)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值