精华内容
下载资源
问答
  • openmv识别二维码,颜色识别与串口通信

    千次阅读 多人点赞 2020-12-10 13:21:16
    目的: 给二维码指定内容:“xxx+xxx”,识别并返回及发送对应序号到串口,同时,正在执行扫码动作时,亮起绿灯,扫码结束后亮起蓝灯。 import sensor, image, time, pyb import ujson from pyb import UART aa = 0...

    目的

    初始目的

    1.识别二维码
    2.识别物体颜色
    3.与stm32串口通信

    进阶想法

    1.给二维码指定内容:“xxx+xxx”,识别并发送到串口;
    2.识别三种颜色,按顺序发送到串口;
    3.待更新(识别条形码并发送至串口)

    二维码识别

    while(True):
        img = sensor.snapshot()
        img.lens_corr(1.8)
        for code in img.find_qrcodes():
            output_str="%s" % code.payload()
    		#output_str为二维码内容
    

    附(草料二维码生成器

    颜色识别

    #颜色阈值
    green_threshold   = (73, 96, -79, -22, -128, 127)
    red_threshold   = (41, 61, 42, 127, -128, 127)
    blue_threshold   = (22, 67, 9, 127, -128, -54)
    
    blobs = img.find_blobs([green_threshold,red_threshold,blue_threshold],x_stride=25,y_stride=50,area_threshold=1000)
    for b in blobs:
    	img.draw_rectangle(b[0:4]) # rect
        #用矩形标记出目标颜色区域
        img.draw_cross(b[5], b[6]) # cx, cy
        #在目标颜色区域的中心画十字形标记
        print(b[8])#b[8]为颜色代号,red=2,green=1,blue=4
    

    串口通信

    openmv上的P4连接stm32的RX,P5连接TX
    1.简单方法

    from pyb import UART
    uart = UART(3, 19200)
    while(True):
    	if uart.any():#判断是否接收到数据
    		getrx = uart.readline()#读取数据
    		uart.write('abc')#发送数据
    

    虽然此法较为简单,但是数据容易在传输的过程中出错,以下是更为便捷的一种方法。

    2.json发送
    openmv可以通过串口直接发送字符串,具体的教程可戳这里->戳我
    在此不多做赘述。
    但我们想要更稳定,高效的通信方法,以下。

    3.按帧传输
    参照这位博主的文章->戳我
    那么假如我想把读取到格式为"xxx+xxx"的二维码内容发送给串口,可以用以下方式。

    #1.定义帧头
    FH = bytearray([0xb3,0xb3])
    uart.write(FH)#串口发送帧头
    #假如已经识别到二维码
    a1,a2,a3 = int(output_str[0]),int(output_str[1]),int(output_str[2])
    b1,b2,b3 = int(output_str[0]),int(output_str[1]),int(output_str[2])
    data=bytearray([a1,a2,a3,b1,b2,b3])#数据转码
    uart.write(data)#串口发送
    

    stm32接收:

    void USART2_IRQHandler(void){
    	
    	static uint8_t rebuf[8]={0},i=0;
    	
    	if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
    	{
    		rebuf[i++]=USART_ReceiveData(USART2);	
    		if(rebuf[0]!=0xb3)//帧头
    			i=0;
    	  if((i==2)&&(rebuf[1]!=0xb3))//判断帧头
    			i=0;
    		if(i>=7)//代表一帧数据完毕
    		{
    				memcpy(OpenMV_Rx_BUF,rebuf,i);
    			i = 0;
     
    		}
    		USART_ClearFlag(USART2,USART_FLAG_RXNE);
    	}	
    }
    

    另外,我们可以通过写小灯闪烁来判断是否成功执行某一步骤

    import pyb
    
    led.off()#小灯闪烁并变蓝
    time.sleep(100)     #延时100ms
    led = pyb.LED(2)
    led.on()
    

    完整代码

    (这里是早期写的代码,能初步实现一些想法,完善后的过一阵子我就会贴出来哈)

    import sensor, image, time, pyb
    import ujson
    from pyb import UART
    
    green_threshold   = (73, 96, -79, -22, -128, 127)
    #(0, 100, -128, -25, -128, 127)
    red_threshold   = (41, 61, 42, 127, -128, 127)
    #(41, 61, 42, 127, -128, 127)
    blue_threshold   = (22, 67, 9, 127, -128, -54)
    #(15, 100, -128, 127, -128, -41)
    #red=2,green=1,blue=4
    getrx = 0
    getcmd = 0
    renum = 0
    colornum = 0
    ptrposition = 0
    sensor.reset()# 初始化摄像头
    sensor.set_pixformat(sensor.RGB565)# 格式为 RGB565.
    sensor.set_framesize(sensor.QQVGA) # 使用 QQVGA 速度快一些
    sensor.skip_frames(time = 2000) # 跳过2000s,使新设置生效,并自动调节白平衡
    sensor.set_auto_gain(False) # 关闭自动自动增益。默认开启的,在颜色识别中,一定要关闭白平衡。
    sensor.set_auto_whitebal(False)
    #关闭白平衡。白平衡是默认开启的,在颜色识别中,一定要关闭白平衡。
    clock = time.clock() # 追踪帧率
    led = pyb.LED(1) # Red LED = 1, Green LED = 1, Blue LED = 2, IR LEDs = 4.
    uart = UART(3, 115200, timeout_char = 1000)
    led.on()
    
    def Rec_NUM1(lista):
        if (lista[0]=='1' and lista[1]=='2' and lista[2]=='3'):
            return 1
        elif (lista[0]=='1' and lista[1]=='3' and lista[2]=='2'):
            return 2
        elif (lista[0]=='2' and lista[1]=='1' and lista[2]=='3'):
            return 3
        elif (lista[0]=='2' and lista[1]=='3' and lista[2]=='1'):
            return 4
        elif (lista[0]=='3' and lista[1]=='1' and lista[2]=='2'):
            return 5
        elif (lista[0]=='3' and lista[1]=='2' and lista[2]=='1'):
            return 6
    
    def Rec_NUM2(lista):
        if (lista[4]=='1' and lista[5]=='2' and lista[6]=='3'):
            return 1
        elif (lista[4]=='1' and lista[5]=='3' and lista[6]=='2'):
            return 2
        elif (lista[4]=='2' and lista[5]=='1' and lista[6]=='3'):
            return 3
        elif (lista[4]=='2' and lista[5]=='3' and lista[6]=='1'):
            return 4
        elif (lista[4]=='3' and lista[5]=='1' and lista[6]=='2'):
            return 5
        elif (lista[4]=='3' and lista[5]=='2' and lista[6]=='1'):
            return 6
    
    while(True):
        clock.tick() # Track elapsed milliseconds between snapshots().
        if uart.any():
            led.off()
            getrx = uart.readline()
            time.sleep(150)     #延时150ms
            led = pyb.LED(2)
            led.on()
            getcmd = int(getrx)
            print(getcmd)
          #  print(img.find_qrcodes())
        img = sensor.snapshot()# 从感光芯片获得一张图像
        img.lens_corr(1.8) # strength of 1.8 is good for the 2.8mm lens.
        blobs = img.find_blobs([green_threshold,red_threshold,blue_threshold],x_stride=25,y_stride=50,area_threshold=1000)
        if(getcmd==2):
            for code in img.find_qrcodes():
                output_str="%s" % code.payload() #方式1
                renum = int(Rec_NUM1(output_str)*10 + Rec_NUM2(output_str))
                uart.write(ujson.dumps(renum))
                getcmd = 0
                led.off()
        if blobs and getcmd==3:
            for b in blobs:
                # Draw a rect around the blob.
                img.draw_rectangle(b[0:4]) # rect
                #用矩形标记出目标颜色区域
                img.draw_cross(b[5], b[6]) # cx, cy
                #在目标颜色区域的中心画十字形标记
                #print(b[5], b[6], b[8])
                #uart.write(ujson.dumps(b[8]))
                #将颜色序号转为比赛序号
                if b[8]==1:
                    colornum=2
                elif b[8]==2:
                    colornum=1
                elif b[8]==4:
                    colornum=3
                print('colornum=',colornum,'output_str[ptrposition]=',output_str[ptrposition])
                #若任务码对应
                if (int(output_str[ptrposition]) == colornum):
                    uart.write('t')
                    ptrposition+=1
                    if ptrposition==4:
                        ptrposition+=1
                    getcmd=0
    
    
    展开全文
  • openmv使用二维码识别程序示列出现问题,我使用openmv二维码识别程序案例但是出现以下两种情况,对于我,很是无解,希望能有朋友解释一下
  • 嵌入式OpenMV识别静态二维码,代码无需更改,有大量注释
  • 利用openmv识别二维码信息,可用于液晶显示屏显示的内容
  • 工程训练大赛openmv二维码、色环、色块识别 可通过串口与单片机通信实现openmv的任务切换
  • 这是我参加全国大学生工程训练大赛智能物流车搬运赛道使用的代码,测试过均正常,K210的MaixPy 版和OPENMV代码好像是通用的,简单改改就能用。
  • OPenMV识别颜色识别物块及检测二维码的进阶应用

    万次阅读 多人点赞 2020-02-25 22:55:12
    摄像头OPenMV入门与Python进阶应用 OpenMV简介 简单的来说,它是一个可编程的摄像头,通过MicroPython语言,可以实现你的逻辑。 而且摄像头本身内置了一些图像处理算法,很容易使用。 适合做DIY相关的项目制作,比如...

    OPenMV摄像头入门与识别颜色物块及二维码的进阶应用

    OpenMV简介

    简单的来说,它是一个可编程的摄像头,通过MicroPython语言,可以实现你的逻辑。
    而且摄像头本身内置了一些图像处理算法,很容易使用。
    适合做DIY相关的项目制作,比如追踪小球的车,云台,或者解魔方的机器人。以及对成本要求很高的嵌入式工业方案,比如流水线物品的分拣。
    足以满足基本的应用功能。目前最新版为OpenMV4,本文也是采用最新版而成。

    前言

    关于openmv IDE的安装与使用,官网就有教程,在此不再赘述。
    笔者以前并未学过Python,但只要有C/C++的基础,对OpenMV编程就不是难事。因为IDE自带了很多例程,在这基础上修改即可。

    软件介绍

    我这次是做嵌入式开发,针对各种颜色的物块进行识别,并且完成了二维码识别。使用stm32F4系列的单片机与OpenMV4进行串口通信。完成这些功能就可以对OpenMV驾轻就熟了。

    识别二维码

    二维码是当今重要的信息载体,并且发展迅速,应用前景很广。
    下附源码:

    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA) # can be QVGA on M7...
    sensor.skip_frames(30) # 修改sensor配置之后, 跳过30帧
    sensor.set_auto_gain(False) # must turn this off to prevent image washout...
    while(a):
        img = sensor.snapshot()
        img.lens_corr(1.8) # strength of 1.8 is good for the 2.8mm lens.
        for code in img.find_qrcodes():
    

    值得注意的是,由于物体的距离不同,我们可以采用不同的像素去采集图像,所以在第三行中,sensor.set_framesize(sensor.QVGA)我们可以根据需要,选择QQVGA、QVGA、VGA等模式。
    倒数第二行img.lens_corr(1.8) # strength of 1.8 is good for the 2.8mm lens.
    这是对图像进行校正,参数可以自行修改。

    至此二维码已经成功读取到ode.payload()中, 例如下图调用。

    if code.payload() ==123:
         qr=1;
    

    识别颜色及物块位置

    我认为这是在嵌入式设计和日常应用中最为常用的功能。
    从颜色格式而言,这里是LAB颜色模型,而不是常见的RGB。
    这里有三对阈值参数
    1.亮度,范围[0,100],从纯黑到纯白;2. a表示从红色到绿色的范围,[127,-128];3. b表示从黄色到蓝色范围,是[127,-128]

    white_threshold_01 = ((95, 100, -18, 3, -8, 4));  #白色阈值
    red_threshold_01 = ((35, 100, 41, 77, 24, 59));
    green_threshold_01 = ((50, 100, -80, -20, 8, 20));
    blue_threshold_01 = ((20, 100, -18, 18, -80, -30));
    
        
    
    while(True):
            clock.tick() # Track elapsed milliseconds between snapshots().
            img = sensor.snapshot() # Take a picture and return the image.
            #  pixels_threshold=100, area_threshold=100
            blobs = img.find_blobs([red_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);      #红色物块
            blobs1 = img.find_blobs([green_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10); #绿色物块
            blobs2 = img.find_blobs([blue_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);   #蓝色物块
            cx=0;cy=0;cx1=0;cy1=0;cx2=0;cy2=0;
            if blobs:
                #如果找到了目标红色
                max_b = find_max(blobs);
                # Draw a rect around the blob.
                img.draw_rectangle(max_b[0:4]) # rect
                #用矩形标记出目标颜色区域
                img.draw_cross(max_b[5], max_b[6]) # cx, cy
                img.draw_cross(160, 120) # 在中心点画标记
                #在目标颜色区域的中心画十字形标记
                cx=max_b[5];
                cy=max_b[6];
                img.draw_line((160,120,cx,cy), color=(127));
                #img.draw_string(160,120, "(%d, %d)"%(160,120), color=(127));
                img.draw_string(cx, cy, "(%d, %d)"%(cx,cy), color=(127));
    
    blob = blobs[0]
    img_ball_r= calc_radius(blob)
     # 小球离镜头的距离 根据我们的公式计算
    ball_distance = K / img_ball_r
    print("小球距离: %d"%ball_distance)
    

    串口设置与stm32通信

    OpenMV自带几种通讯方式:串口、I2C、SPI
    笔者采用最为方便的串口通讯。
    注意这里的波特率,要配置一致。

    uart = UART(3,115200)   #定义串口3变量
            uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
    

    然后定义串口发送数据包的格式:

    def sending_data(code,cx,cy,cx1,cy1,cx2,cy2):
                global uart;
                #frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
                #data = bytearray(frame)
                data = ustruct.pack("<bbhhhhhhhb",              #格式为俩个字符俩个短整型(2字节)
                               0x2C,                       #帧头1
                               0x12,                       #帧头2
                               int(code), # up sample by 4    #数据1
                               int(cx), # up sample by 4    #数据1
                               int(cy), # up sample by 4    #数据2
                               int(cx1), # up sample by 4    #数据1
                               int(cy1), # up sample by 4    #数据2
                               int(cx2), # up sample by 4    #数据1
                               int(cy2), # up sample by 4    #数据2
                               0x5B)
                uart.write(data);   #必须要传入一个字节数组
    

    我设置了两个帧头,一个帧尾,均为一字节,如下对应“b”。中间的数据为7个两字节,如下对应“h”。
    data = ustruct.pack("<bbhhhhhhhb",
    这一行中可以对应着修改,“b”、"h"等以下表对应。

    #pack各字母对应类型

    #x   pad byte        no value            1
    #c   char            string of length 1  1
    #b   signed char     integer             1
    #B   unsigned char   integer             1
    #?   _Bool           bool                1
    #h   short           integer             2
    #H   unsigned short  integer             2
    #i   int             integer             4
    #I   unsigned int    integer or long     4
    #l   long            integer             4
    #L   unsigned long   long                4
    #q   long long       long                8
    #Q   unsilong long   long                8
    #f   float           float               4
    #d   double          float               8
    #s   char[]          string              1
    #p   char[]          string              1
    #P   void *          long
    

    串口接收函数:

     def recive_data():
            global uart
            if uart.any():
                tmp_data = uart.readline();
                print(tmp_data)
    

    注:本人只让OpenMV对单片机单向通信,所以在例程中并未使用此串口接收函数。

    stm32例程:

    OpenMV.h

    #ifndef __Openmv_H
    #define __Openmv_H
    #include "usart.h"
    struct openmv
    {
    	s16 qr;
    	s16 a;
    	s16 b;
    	s16 c;
    	s16 d;
    	s16 e;
    	s16 f;
    };
     void OpenMV_Handler(UART_HandleTypeDef *huart);
    #endif
    

    OpenMV.c

    #include "OpenMV.h"
    #include <string.h>
    struct openmv 		stcopenmv;
    extern u8 RxTemp ;
    
    
     void OpenMV_Handler(UART_HandleTypeDef *huart)
    {
      /* Prevent unused argument(s) compilation warning */
    	
    static u8 aRxBuffer[20];
    static u8 aRxCnt = 0;	
    static u8 state = 0;	
    
    	if (state == 0&&RxTemp==0x2C) //数据头不对,则重新开始寻找0x2c数据头
    	{
         state = 1;
    	}
    	else if (state == 1&&RxTemp==0x12) //数据头不对,则重新开始寻找0x12数据头
    	{
         state =2;
    		 aRxCnt=0;
    	}
    	else if (state == 2) //数据不满11个,则返回
    	{
    		aRxBuffer[aRxCnt++]=RxTemp;
    		if (aRxCnt>=14)//数据不满11个,返回
    		{
    		memcpy(&stcopenmv,&aRxBuffer[0],14);
    		aRxCnt=0;
    		state=0;
    		}
    	}
    	else state=0;
    	
      /* NOTE: This function should not be modified, when the callback is needed,
               the HAL_UART_RxCpltCallback could be implemented in the user file
       */
    }
    int COLOR_Order()
    {
    	if(stcopenmv.a<stcopenmv.c&&stcopenmv.a<stcopenmv.e)
    	{
    		if(stcopenmv.c<stcopenmv.e)
    				return 1;
    	  else
    		    return 2;	
    	}
    	else if(stcopenmv.c<stcopenmv.a&&stcopenmv.c<stcopenmv.e)
    	{
    		if(stcopenmv.a<stcopenmv.e)
    				return 3;
    	  else
    		   return 4;	
    	}
    	else if(stcopenmv.e<stcopenmv.c&&stcopenmv.e<stcopenmv.a)
    	{
    		if(stcopenmv.a<stcopenmv.c)
    				return 5;
    	  else
    		    return 6;	
    	}
    	return 0;
    }
    

    main函数调用的相关代码:

    #include "OpenMV.h"
    
    extern u8 RxTemp ;
    extern struct openmv 		stcopenmv;
    
      MX_USART3_UART_Init();
      HAL_UART_Receive_IT(&huart3,&RxTemp,1); 
    

    经过以上初始化,就已经可以读取OpenMV串口发过来的值了。
    比如以下就可以通过我自己的LED函数显示出来:
    其中的stcopenmv.qr是读取二维码的值。

    OLED_ShowNum(0,0,stcopenmv.a,3,16);
    OLED_ShowNum(100,0,stcopenmv.qr,3,16);
    OLED_ShowNum(0,2,stcopenmv.c,3,16);
    OLED_ShowNum(0,4,stcopenmv.e,3,16);
    OLED_ShowNum(100,4,stcopenmv.f,3,16);
    

    OpenMV编辑器全例程如下:

    import sensor, image, time, math
    from pyb import UART
    import json
    import ustruct
    
    #亮度,范围[0,100],从纯黑到纯白;a表示从红色到绿色的范围,[127,-128];b表示从黄色到蓝色范围,是[127,-128]
    white_threshold_01 = ((95, 100, -18, 3, -8, 4));  #白色阈值
    red_threshold_01 = ((35, 100, 41, 77, 24, 59));
    green_threshold_01 = ((50, 100, -80, -20, 8, 20));
    blue_threshold_01 = ((20, 100, -18, 18, -80, -30));
    threshold = [50, 50, 0, 0, 0, 0] # Middle L, A, B values.
    
    QRCode_1="123";
    QRCode_2="132";
    QRCode_3="213";
    QRCode_4="231";
    QRCode_5="312";
    QRCode_6="321";
    
    qr=0
    a=1
    K=5000 # K是我们计算出来的常数
    
    
    sensor.reset()
    sensor.set_pixformat(sensor.RGB565)
    sensor.set_framesize(sensor.QVGA) # can be QVGA on M7...
    sensor.skip_frames(30) # 修改sensor配置之后, 跳过30帧
    sensor.set_auto_gain(False) # must turn this off to prevent image washout...
    while(a):
        img = sensor.snapshot()
        img.lens_corr(1.8) # strength of 1.8 is good for the 2.8mm lens.
        for code in img.find_qrcodes():
            if code.payload() == QRCode_1 :
                qr=1;
            elif code.payload() == QRCode_2 :
                qr=2;
            elif code.payload() == QRCode_3 :
                qr=3;
            elif code.payload() == QRCode_4 :
                qr=4;0
                .3
            elif code.payload() == QRCode_5 :
                qr=5;
            elif code.payload() == QRCode_6 :
                qr=6;
            else :
                qr=7;
            a=0
            print(code)
            print(qr)
            print(QRCode_4)
    
    
    else:
            sensor.reset()
            sensor.set_pixformat(sensor.RGB565)
            sensor.set_framesize(sensor.QVGA)
            sensor.skip_frames(time = 2000)
            sensor.set_auto_gain(False) # must be turned off for color tracking
            sensor.set_auto_whitebal(False) # must be turned off for color tracking
            clock = time.clock()
    
            uart = UART(3,115200)   #定义串口3变量
            uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters
    
            def calc_radius(blob):
                            # 计算图像中色块的半径 , 比较粗暴
                     return (blob.w() + blob.h()) / 2
    
            def find_max(blobs):    #定义寻找色块面积最大的函数
                max_size=0
                for blob in blobs:
                    if blob.pixels() > max_size:
                        max_blob=blob
                        max_size = blob.pixels()
                return max_blob
    
    
    
    
            def sending_data(code,cx,cy,cx1,cy1,cx2,cy2):
                global uart;
                #frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
                #data = bytearray(frame)
                data = ustruct.pack("<bbhhhhhhhb",              #格式为俩个字符俩个短整型(2字节)
                               0x2C,                       #帧头1
                               0x12,                       #帧头2
                               int(code), # up sample by 4    #数据1
                               int(cx), # up sample by 4    #数据1
                               int(cy), # up sample by 4    #数据2
                               int(cx1), # up sample by 4    #数据1
                               int(cy1), # up sample by 4    #数据2
                               int(cx2), # up sample by 4    #数据1
                               int(cy2), # up sample by 4    #数据2
                               0x5B)
                uart.write(data);   #必须要传入一个字节数组
    
            def recive_data():
                global uart
                if uart.any():
                    tmp_data = uart.readline();
                    print(tmp_data)
    
    
    
            #mainloop
            while(True):
                clock.tick() # Track elapsed milliseconds between snapshots().
                img = sensor.snapshot() # Take a picture and return the image.
                #  pixels_threshold=100, area_threshold=100
                blobs = img.find_blobs([red_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
                blobs1 = img.find_blobs([green_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
                blobs2 = img.find_blobs([blue_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
                cx=0;cy=0;cx1=0;cy1=0;cx2=0;cy2=0;
                if blobs:
                    #如果找到了目标颜色
                    max_b = find_max(blobs);
                    # Draw a rect around the blob.
                    img.draw_rectangle(max_b[0:4]) # rect
                    #用矩形标记出目标颜色区域
                    img.draw_cross(max_b[5], max_b[6]) # cx, cy
                    img.draw_cross(160, 120) # 在中心点画标记
                    #在目标颜色区域的中心画十字形标记
                    cx=max_b[5];
                    cy=max_b[6];
                    img.draw_line((160,120,cx,cy), color=(127));
                    #img.draw_string(160,120, "(%d, %d)"%(160,120), color=(127));
                    img.draw_string(cx, cy, "(%d, %d)"%(cx,cy), color=(127));
    
                    blob = blobs[0]
                    img_ball_r= calc_radius(blob)
                    # 小球离镜头的距离 根据我们的公式计算
                    ball_distance = K / img_ball_r
                    print("小球距离: %d"%ball_distance)
    
                if blobs1:
                        #如果找到了目标颜色
                        max_b = find_max(blobs1);
                        # Draw a rect around the blob.
                        img.draw_rectangle(max_b[0:4]) # rect
                        #用矩形标记出目标颜色区域
                        img.draw_cross(max_b[5], max_b[6]) # cx, cy
                        img.draw_cross(160, 120) # 在中心点画标记
                        #在目标颜色区域的中心画十字形标记
                        cx1=max_b[5];
                        cy1=max_b[6];
                        img.draw_line((160,120,cx1,cy1), color=(127));
                        #img.draw_string(160,120, "(%d, %d)"%(160,120), color=(127));
                        img.draw_string(cx1, cy1, "(%d, %d)"%(cx1,cy1), color=(127));
                if blobs2:
                        #如果找到了目标颜色
                        max_b = find_max(blobs2);
                        # Draw a rect around the blob.
                        img.draw_rectangle(max_b[0:4]) # rect
                        #用矩形标记出目标颜色区域
                        img.draw_cross(max_b[5], max_b[6]) # cx, cy
                        img.draw_cross(160, 120) # 在中心点画标记
                        #在目标颜色区域的中心画十字形标记
                        cx2=max_b[5];
                        cy2=max_b[6];
                        img.draw_line((160,120,cx2,cy2), color=(127));
                        #img.draw_string(160,120, "(%d, %d)"%(160,120), color=(127));
                        img.draw_string(cx2, cy2, "(%d, %d)"%(cx2,cy2), color=(127));
    #            sending_data(cx,cy,cx,cy,cx,cy); #发送点位坐标
                sending_data(qr,cx,cy,cx1,cy1,cx2,cy2); #发送点位坐标
                recive_data();
                #time.sleep(1000)
    
            #pack各字母对应类型
            #x   pad byte        no value            1
            #c   char            string of length 1  1
            #b   signed char     integer             1
            #B   unsigned char   integer             1
            #?   _Bool           bool                1
            #h   short           integer             2
            #H   unsigned short  integer             2
            #i   int             integer             4
            #I   unsigned int    integer or long     4
            #l   long            integer             4
            #L   unsigned long   long                4
            #q   long long       long                8
            #Q   unsilong long   long                8
            #f   float           float               4
            #d   double          float               8
            #s   char[]          string              1
            #p   char[]          string              1
            #P   void *          long
    

    硬件

    在这里插入图片描述

    电源

    通过USB-type c线供电。据笔者实验,这是仅有的供电方式,如果这里坏了,就得重新买一个了。

    焊接接口

    笔者用的是串口,就连usart3(P10、11) 当然,别忘了共地哈。

    展开全文
  • 使用OpenCV识别二维码

    千次阅读 2021-09-12 11:35:03
    程序: # -*-coding:utf-8 -*- import cv2 as cv import numpy as np # 加载图片 src_image = cv.imread("./webwxgetmsgimg.jpeg") ...qrcoder = cv.QRCodeDetector() ...codeinfo, points, straight_qrcode = ...

    二维码广泛应用于我们的日常生活中,比如微信和支付宝支付,火车票,商品标识等等,二维码种类有很多,包括QR Code, Data Matrix, Code One等,日常生活中常用的二维码是QR二维码。

    各类二维码的特征如下:

    QR二维码的识别过程大致分成两个阶段,首先搜索二维码的位置探测图形,即QR二维码三个顶点处的回字区域,QR二维码位置以4个顶点坐标形式给出,之后对二维码进行解码,提取其中的信息。

    QR二维码识别是Opencv4新增加的功能,OpenCV4提供了相关函数直接解码QR二维码并读取其中的信息,在OpenCV4之前的版本中,对QR二维码的识别需要借助于第三方工具,常用的是zbar解码库。

    针对QR二维码识别的两个过程,OpenCV4提供了多个函数用于实现每个过程,这些函数分别是定位QR二维码的detect函数,根据定位结果解码二维码的decode函数,以及同时进行定位和解码的detectAndDecode函数。

    定位QR二维码的位置不但可以用于解码QR二维码,而且可以用于视觉定位,在利用QR二维码定位的任务中,有时不需要对QR二维码进行解码,而是直接使用4个顶点的坐标,因此指定为而不解码QR二维码可以加快系统的运行速度。

    程序:

    # -*-coding:utf-8 -*-
     
    import cv2 as cv
    import numpy as np
     
    # 加载图片
    src_image = cv.imread("./webwxgetmsgimg.jpeg")
    # 实例化
    qrcoder = cv.QRCodeDetector()
    # qr检测并解码
    codeinfo, points, straight_qrcode = qrcoder.detectAndDecode(src_image)
    # 绘制qr的检测结果
    cv.drawContours(src_image, [np.int32(points)], 0, (0, 0, 255), 2)
    print(points)
    # 打印解码结果
    print("qrcode :", codeinfo)
    cv.imshow("result", src_image)
    cv.waitKey(0)

    包含二维码的图片

    运行结果:

    src_img是待检测是否含有QR二维码的灰度图像或者彩色图像,points包含QR二维码的最小区域四边形的四个顶点坐标,即二维码的四个顶点坐标。结果以字符串的形式返回。

    结束!

    展开全文
  • 前言 刚刚学完OpenCv的基础部分,上手来一个简单的练习,定位识别二维码。 二维码有三个定位点,通过定位三个定位点来定位二维码的位置与大小。 处理步骤 灰度处理 滤波 二值化 发现轮廓,并导出子轮廓大于两个的父...

    前言

    刚刚学完OpenCv的基础部分,上手来一个简单的练习,定位识别二维码。

    二维码有三个定位点,通过定位三个定位点来定位二维码的位置与大小。

    处理步骤

    1. 灰度处理
    2. 滤波
    3. 二值化
    4. 发现轮廓,并导出子轮廓大于两个的父轮廓
    5. 筛选出三个轮廓,条件:有一个垂直角
    6. 计算倾斜角度并原图,将二维码抠出

    成果展示

    将原图标记出定位点:

    输出图像均为

    由输出可看出,任何角度的二维码,都可以正确的识别并取出。

    代码展示

    #include<opencv2/opencv.hpp>
    #include<opencv2/core/mat.hpp>
    #include<iostream>
    #include<vector>
    using namespace std;
    using namespace cv;
    
    int threshold_value = 80;
    int threshold_max = 255;
    Mat src, dst;
    
    
    int main()
    {
    	src = imread("C:/Users/LBJ/Desktop/二维码识别/二维码1.png");
    	if (!src.data)
    	{
    		cout << "The iamge is empty" << endl;
    		return -1;
    	}
    
    	src.copyTo(dst);
    	namedWindow("output_image", WINDOW_AUTOSIZE);
    	namedWindow("Input_Image", WINDOW_AUTOSIZE);
    	
    	cvtColor(src, src, CV_BGR2GRAY);
    	blur(src, src, Size(3, 3), Point(-1, -1));;
    
    	Mat bin_output;
    	vector<vector<Point>> contours;
    	vector<Vec4i> hierachy;
    	vector<Point> convexs;       //用来储存三个标记框的点集,画最小矩形,即为二维码的区域
    	vector<vector<Point>> Qrprint;
        threshold(src, bin_output, threshold_value, threshold_max, THRESH_BINARY);
    
    /**************************************通过轮廓信息查找二维码的标记框**********************************************/
    	findContours(bin_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    
    	for (size_t i = 0; i < contours.size(); i++)
    	{
    		int j = i, temp = 0;
    		while (hierachy[j][2] != -1)
    		{
    			temp++;
    			j = hierachy[j][2];
    		}
    		if (temp >= 2)
    		{
    	
    
    			Qrprint.push_back(contours[i]);   //将识别到的定位点放入数组中
    
    			drawContours(dst, contours, i, Scalar(0, 0, 255), -1, 8, hierachy, 0, Point(0, 0));
    			cout << contours[i] << endl;
    		}
    
    	}
    /********************************************************************************************************************/
    
    /*************************通过两两垂直的关系,筛选出正确的三个识别框,储存子Q中************************************************/
    	vector<RotatedRect> Qr_Rect(Qrprint.size());
    	vector<Point> Center_Point(Qrprint.size());
    
    	for (size_t i = 0; i < Qrprint.size(); i++)
    	{
    		Qr_Rect[i] = minAreaRect(Qrprint[i]);
    		Center_Point[i] = Qr_Rect[i].center;
    		circle(dst, Center_Point[i], 5, Scalar(0, 255, 0), -1, 8);
    	}
    
    	int Q[3];
    	for (size_t i = 0; i < Qrprint.size(); i++)
    	{
    		for (size_t j = 0; j < Qrprint.size(); j++)
    		{
    			for (size_t k = 0; k < Qrprint.size(); k++)
    			{
    				if ( i!=j && i!=k && j!=k )
    				{
    					double k1, k2, k3;
    					double dx, dy;
    					dx = Center_Point[i].x - Center_Point[j].x;
    					dy = Center_Point[i].y - Center_Point[j].y;
    					k1 = dy / dx;
    					dx = Center_Point[i].x - Center_Point[k].x;
    					dy = Center_Point[i].y - Center_Point[k].y;
    					k2 = dy / dx;
    					dx = Center_Point[j].x - Center_Point[k].x;
    					dy = Center_Point[j].y - Center_Point[k].y;
    					k3 = dy / dx;
    
    					if ((k1*k2 > -1.1&&k1*k2 < -0.9)) {
    						Q[0] = i; Q[1] = j; Q[2] = k;
    					}
    					else if ((k1*k3 > -1.1&&k1*k3 < -0.9)) {
    						Q[0] = j; Q[1] = i; Q[2] = k;
    					}
    					else if ((k3*k2 > -1.1&&k3*k2 < -0.9)) {
    						Q[0] = k; Q[1] = j; Q[2] = i;
    					}
    					else { continue; }
    					//q1储存了直角点的信息
    				}
    
    			}
    
    		}
    
    	}
    
    	/**************************************在原图里标记出二维码的位置***************************************/
    	for (size_t i = 0; i < 3; i++)
    	{
    		convexs.insert(convexs.end(), Qrprint[Q[i]].begin(), Qrprint[Q[i]].end());
    	}
    	Point2f ptr[4];
    	RotatedRect rect = minAreaRect(convexs);
    	rect.points(ptr);
    	for (int i = 0; i < 4; i++)
    	{
    		line(dst, ptr[i], ptr[(i + 1) % 4], Scalar(0, 255, 0), 5, 8);
    
    	}
    
    	/**************************通过直角点位置计算旋转角度并且将二维码抠出********************************/
    	double angel = rect.angle;; //计算旋转角度
    	if (Center_Point[Q[0]].x< Center_Point[Q[1]].x && Center_Point[Q[0]].x < Center_Point[Q[2]].x)
    	{
    	}
    	else if (Center_Point[Q[0]].y > Center_Point[Q[1]].y && Center_Point[Q[0]].y > Center_Point[Q[2]].y)
    	{
    		angel -= 90;
    
    	}
    	else if (Center_Point[Q[0]].x > Center_Point[Q[1]].x && Center_Point[Q[0]].x > Center_Point[Q[2]].x)
    	{
    		angel -= 180;
    	}
    	else if (Center_Point[Q[0]].y < Center_Point[Q[1]].y && Center_Point[Q[0]].y < Center_Point[Q[2]].y)
    	{
    		angel -= 270;
    
    	}
    
    	Mat  Rotation = getRotationMatrix2D(rect.center, angel, 1.0);
    	warpAffine(src, src, Rotation, src.size());
    
    	Mat Result = src(Rect(rect.center.x - (rect.size.width / 2), rect.center.y - (rect.size.height / 2), rect.size.width, rect.size.height));
    
    	imshow("Input_Image", dst);
    	imshow("output_image", Result);
    
    	
    
    	waitKey(0);
    	return 0;
    }

    可优化部分

    1、识别二维码三个定位点的方法是寻找子轮廓数大于二的父轮廓,改成寻找子轮廓数大于二的轮廓的最小子轮廓,效果可能会好一点。

    2、对于畸变后的二维码无法识别,后期可以尝试改进。

    展开全文
  • openmv和stm32串口通信完成二维码识别

    千次阅读 多人点赞 2021-03-21 22:28:25
    openmv和stm32串口通信完成二维码识别 文章目录前言一、所用的硬件:二、openmv端2.stm32端总结 前言 注:我只是个大一的小白,本文只完成基本功能,希望能帮助有困惑的人(我也是刚刚走出谜团,大佬勿喷。) 工训...
  • 最近在搞openmv识别带有二维码的小木块,因为车是运动的,想让他看见这种木块快速停下来
  • 一个基于openmv二维码识别程序,可以实现手自动一体的二维码识别
  • OpenMV交通灯识别例程

    2019-05-23 17:43:27
    OpenMV识别交通灯例程,仅需根据环境修改交通灯红、绿、黄颜色阈值即可,思路清晰,识别率高。

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 165
精华内容 66
关键字:

openmv识别二维码