2018-03-11 11:29:22 zxpcus 阅读数 2052

STM32黑线 黑点图像识别

 

注:正点原子mini板+ov7670摄像头  ___改编扩展实验9 摄像头实验

下面是代码部分注释说明

Part1 :黑线识别

主函数说明

 

         camera_refresh();   //更新显示     

         Image_Filter();/*-----        图像中值滤波函数【1*3】-----*/

         Get_Black_Line2();//黑线识别

         /*Get_Black_Line3();//黑点识别,去掉注释,将Get_Black_Line2();注释掉生效

在主函数                            printf("(%d\n %d \n)",z1,z2);在串口观察坐标(不一定是z1,z2看处于哪种模式),在LCD可以观察到图像,具体算法较为简单,简略为对X,Y轴扫描若一开始检测连续多点都为黑点,则认为检测到黑线边界,两个边界的中点即为黑线位置,黑点检测同上


源代码资源链接:https://download.csdn.net/download/zxpcus/10280066

2017-09-11 22:14:50 qq_33894122 阅读数 2810
博主最近参加一个比赛,需要识别白色纸片上的黑色胶带,由于单片机跑不了opencv等一些高级算法,于是就想到了用树莓派 + python 跑opencv,实际测试效果还挺好
下面贴代码
#coding=utf_8
import multiprocessing
from threading import Timer
import numpy as np
import cv2
import time

i = 0
time_interval = 1.0
lower_blue = np.array([0,0,0])
upper_blue = np.array([170,255,46])
cap = cv2.VideoCapture(0)//打开Pi摄像头

area_max = 19000  //最大面积
area_min = 6000   //最小面积

pyserial_test=serial.Serial("/dev/ttyS0",115200)

###########################计算帧率函数############################################
def frame_rate():
	global i
	x = i
	print x
	i = 0
	t = Timer(time_interval,frame_rate)
	t.start()

#####################################################################################



###########################主图像处理函数############################################
def main():
	uart_send_data = multiprocessing.Process(name = "uart_send_data",
			target = uart_send,
			args = ())
	while(True):
		global i
		i = i + 1
		X = []
		Y = []
		 ret, frame = cap.read()
		gray   = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
		canny = cv2.Canny(gray, 30, 150)
		contours, hierarchy = cv2.findContours(
							canny,
							cv2.RETR_TREE,
							cv2.CHAIN_APPROX_NONE)
		#寻找轮廓
		F = []
		for j in range(len(contours)):
			area = cv2.contourArea(contours[j])
			if (area > area_min)and(area < area_max):
				# print "Area",cv2.contourArea(contours[i])
				F.append(contours[j])
		
		cv2.drawContours(gray, F, -1, (0,255,0), 3)
		cv2.imshow("gray",gray )
		str_b = str(B)
		str_c = str(C)
		while (len(str_b) < 6):
			str_b = '\0' + str_b
		while (len(str_c) < 6):
			str_c = '\0' + str_c
		DATA = str(A) + str_b + str_c + str(D) +'\n'
		# time.sleep(1)
		pyserial_test.write(DATA)
		if cv2.waitKey(1) & 0xFF == ord('q'):
			break
	cap.release()
	cv2.destroyAllWindows()
######################################################################################


###########函数入口###################################################################
if __name__=='__main__':
	t = Timer(time_interval,frame_rate)
	t.start()
	try:
		main()
	except KeyboardInterrupt:
		if pyserial_test!=None:
			pyserial_test.close()


主要想法是树莓派捕捉到摄像头每一帧图像,然后灰度化,得到图像gray,然后将gray图像作为参数传递给canny函数,canny函数主要是检测物体轮廓,得到canny图像,再将canny图像(二值化)传递给找轮廓函数,findContours返回参数有两个,其中counters是一个列表,里面存放了每一个轮廓信息,然后遍历每一个轮廓信息,对其求面积,面积满足一定要求时,将counters列表元素append到F列表中,这样F列表中每一个元素就是满足面积要求的轮廓信息

2019-07-18 22:19:47 weixin_43444989 阅读数 513
import sensor, image, time
thresholds = [(0, 50, -24,-1, -18, 6)]#LAB阈值
#顺序:(L Min, L Max, A Min, A Max, B Min, B Max)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # 关闭增益(色块识别时必须要关)
sensor.set_auto_whitebal(False) # 关闭白平衡
clock = time.clock()#定义时钟对象clock



while(True):
    clock.tick()#返回以毫秒计的通电后的运行时间。
    img = sensor.snapshot()#抓取一帧的图像并返回一个image对象
    #img.find_blobs()查找图像中所有色块,并返回包含每个色块的色块对象列表
    for blob in img.find_blobs(thresholds, pixels_threshold=50, area_threshold=50, merge=False):
    #若一个色块的边界框区域小于 area_threshold ,则会被过滤掉。
    #若一个色块的像素数小于 pixel_threshold ,则会被过滤掉。   
    #merge_cb 可设置为用以调用两个即将合并的色块的函数,以禁止或准许合并。

        #if blob.elongation() > 0.5:#可能是用来判断色块边界框形状的
            #img.draw_edges(blob.min_corners(), color=(255,0,0))
            #img.draw_line(blob.major_axis_line(), color=(0,255,0))
            #img.draw_line(blob.minor_axis_line(), color=(0,0,255))
        
        img.draw_rectangle(blob.rect())#画矩形框 blob.rect() ---> 返回一个矩形元组(可当作roi区域)
        img.draw_cross(blob.cx(), blob.cy())#画十字 blob.cx(), blob.cy() --->返回中心点x和y坐标     
     
        
    print(clock.fps())#clock.fps() ---> 停止追踪运行时间,并返回当前FPS(必须先调用tick)。

进一步定位黑线文章,戳这里

 

2014-08-24 19:13:30 fengdehuhuan122 阅读数 1213

androi、opencv黑线位置识别并使用蓝牙发送

首先声明本人也是安卓开发菜鸟,在这里发帖只是为了跟大家互相学习,交流经验。之前做过一个类似于闹钟的app,花了很长时间,这次因为有了上次的开发经验用的时间会短一些,不过用的都是别人的源代码,距离自己编写还有很长的路要走。

本次我主要使用了两个代码,这里我给出网址,大家可以去下载:

1:http://download.csdn.net/detail/fengdehuhuan122/7810953  蓝牙串口

2:我用的源码地址为

http://www.opencv.org.cn/forum.php?mod=viewthread&tid=31817&extra=page%3D2,不过正如楼主所说的在有些手机上是不能用的,我找到了问题的所在主要是将AutoDriodViewBase中的releaseCamera()函数中if的内容去掉即可。如果大家不想自己新建工程,可以到这里下载工程文件:http://download.csdn.net/detail/fengdehuhuan122/7811023

最后说说我修改以后的代码实现的功能:

最近再做一个机器人跟随黑线行走的功能,为了更加体现创新性,所以使用手机进行识别提取。本代码的功能主要是利用手机提取黑线,将黑线位置利用手机的蓝牙通过蓝牙转串口设备发送给单片机,单片机在进行决策,蓝牙转串口设备淘宝有卖的,我用的是HC-05。现在功能已实现,并且稳定性较好。下载地址:   http://download.csdn.net/download/fengdehuhuan122/7811249

部分安卓代码:

/********************数据提取程序******************/
                bitmapi0=1;
                bitmapi1=1;
                bitmapi2=1;       //黑点个数清零,之所以为1是因为它会被作为除数,如果置零会报错
                for(bitmapx=0;bitmapx<bmp.getWidth();bitmapx++)//循环提取
                {
                   //bmp.getWidth();
                  //for(int k=100;k<200;k++)
                //bmp.setPixel(bitmapx,k,0xFFFFFFFF);
                  if(bmp.getHeight()>700)  //该语句保证下面的正确运行,不然会出错。虽说我的手机分辨率是1280*800,但如果不这样有时会因为读取问题出错
                  {
                       if(bmp.getPixel(bitmapx,bmp.getHeight()-600) ==0xFF000000)         
                      {
                         linecenter0 =linecenter0+bitmapx;//将黑点所在坐标值累加
                         bitmapi0++;
                       }
                       if(bmp.getPixel(bitmapx,bmp.getHeight()-400) ==0xFF000000)         
                       {
                        linecenter1 =linecenter1+bitmapx;
                        bitmapi1++;
                        }
                       if(bmp.getPixel(bitmapx,bmp.getHeight()-200) ==0xFF000000)         
                       {
                        linecenter2 =linecenter2+bitmapx;
                        bitmapi2++;
                        }                       //提取第200、400、600行的黑点个数
                  }
                }
                linecenter0 =linecenter0/bitmapi0;
                linecenter1 =linecenter1/bitmapi1;
                linecenter2 =linecenter2/bitmapi2;//求取平均值,算是一个滤波吧
                blackpoint0 =bitmapi0;
                blackpoint1 =bitmapi1;
                blackpoint2 =bitmapi2;           //黑点个数赋值
           /************************************************/
 
 
Runnable runnable = newRunnable()//定时程序
   { 
        @Override 
        public void run() { 
            // TODO Auto-generated method stub 
            // 在此处添加执行的代码 
            handler.postDelayed(this, 200);// 200ms一次 
            if(flagb==0)
             Toast.makeText(null,"蓝牙未打开!", Toast.LENGTH_SHORT).show();
        else if(flagb==1)
        {
        long Center0=AutoDriodViewBase.linecenter0;
        long Center1=AutoDriodViewBase.linecenter1;
        long Center2=AutoDriodViewBase.linecenter2;
       
        if((Center0>1280)||(Center0==0)||(AutoDriodViewBase.blackpoint0<30))
             Center0=LastCenter0;
        if((Center1>1280)||(Center1==0)||(AutoDriodViewBase.blackpoint1<30))
             Center1=LastCenter1;
        if((Center2>1280)||(Center2==0)||(AutoDriodViewBase.blackpoint2<30))
             Center2=LastCenter2;
        //当黑点位置超出屏幕范围则继续利用上一次的值,当然黑点是不可能超出屏幕范围,主要是防止定时的时候LastCenter没有除bitmapi
        LastCenter0=Center0;
        LastCenter1=Center1;
        LastCenter2=Center2;
        {
        try{
             OutputStreamos = _socket.getOutputStream();   //蓝牙连接输出流
             //蓝牙发送数据"@"、"#"和"*"分别为帧头和帧尾校验
             bytebuf0='@';
             bytebuf1='#';
             bytebuf2=(byte) (Center0/256);
             bytebuf3=(byte) (Center0%256);
             bytebuf4=(byte) (Center1/256);
             bytebuf5=(byte) (Center1%256);
             bytebuf6=(byte) (Center2/256);
             bytebuf7=(byte) (Center2%256);
            //这里数据发送的是16进制的格式。如果用串口调试助手是,注意转换,16进制和hex码、字符串的区别
             bytebuf8=(byte) (buf0+buf1+buf2+buf3);//和校验
             bytebuf9='*';
             os.write(buf0);
             os.write(buf1);
             os.write(buf2);
             os.write(buf3);
             os.write(buf4);
             os.write(buf5);
             os.write(buf6);
             os.write(buf7);
             os.write(buf8);
             os.write(buf9);
            
//               for(byte b : bos)
//               {
//                    os.write(b);
//                }
        }catch(IOExceptione){     
        } 
        }
        }
        }  
}; 

单片机接收中断程序:

ch=uart_receive();//接收
    buf[receive_count]=ch;//数组赋值
   
   if(buf[receive_count]=='@'&&receive_count==0)  //帧头‘@'
          {
                   uart_sum=buf[receive_count];
                   receive_count=1;
          }
          elseif(buf[receive_count]=='#'&&receive_count==1)  //帧头'#'
          {
                   uart_sum+=buf[receive_count];
                   receive_count=2;
          }
          elseif(receive_count>=2&&receive_count<8)//数据段
          {
                   uart_sum+=buf[receive_count];
                   receive_count++;
          }
          elseif(receive_count==8&&buf[receive_count]==uart_sum) //和校验
          {
                   receive_count++;
          }
          elseif(receive_count==9&&buf[receive_count]=='*') //帧尾‘*‘
          {
                   receive_count=0;
 
    CenterXNew0=buf[2]*256+buf[3];
    CenterXNew1=buf[4]*256+buf[5];
    CenterXNew2=buf[6]*256+buf[7];
 
          }                                   
          else
          {
                   receive_count=0;
          }

至于串口用多少的波特率,可以自己设置。最后,有什么问题尽管提,互相学习!

2018-09-25 15:07:01 yst19910702 阅读数 205

1 UILabel 圆角处理后 出现黑线的处理办法;

仔细看在上面会出现一条黑线,时隐时现,看层级图也没问题,原因是ULabel设置可变宽度时,有小数。

方法 1;

只需将宽度转成整型数据即可:[titlelabelsetFrame:CGRectMake(titleLabelX,titlelabelY,(int)textSize.width,labelHeight)];

原因是ULabel设置可变宽度时,有小数。只需将宽度转成整型数据即可:

[titlelabel setFrame:CGRectMake(titleLabelX, titlelabelY, (int)textSize.width, labelHeight)];

方法2:

将:CGRectMake(0, 0 , 100, 100)

换成

 CGRectIntegral( CGRectMake(0, 0 , 100, 100));

方法3:

加个边框 背景色为lable 的背景色 bord宽度1即可,这个方法比较省事,效果还行;

 

其他 :

label Attribute 的一些使用: https://blog.csdn.net/myinclude/article/details/52816217

label 富文本 :https://www.jianshu.com/p/73d098d638cf

                         https://www.jianshu.com/p/1d00a2c9dfd8

模式识别技术

阅读数 800

没有更多推荐了,返回首页