写在前面:由于最近做比赛和着急,有很多东西都是着急去实现并没有做整理,直到昨天才觉得感觉到内心的空虚,发现知识并没有成型,所以决定来写写总结。做些看似有意义的东西。
在官网中有详细介绍:https://singtown.com/product/373/openmv-cam-m7/
在这里着重说一下LAB色彩空间,灰度图和二值化,因为这个是做巡线和色域识别的重点。
1、LAB色彩空间:Lab颜色空间中,L亮度;a的正数代表红色,负端代表绿色;b的正数代表黄色,负端代表兰色。不像RGB和CMYK色彩空间,Lab颜色被设计来接近人类视觉。
而一个颜色的阈值结构是这样的:(minL, maxL, minA, maxA, minB, maxB)
2、灰度图:灰度图就是灰的咯。灰度图阈值(min, max)。
3、二值化:将在thresholds内的图像部分的全部像素变为1白,将在阈值外的部分全部像素变为0黑。
image.find_blobs(thresholds, roi=Auto, x_stride=2, y_stride=1, invert=False, area_threshold=10, pixels_threshold=10, merge=False, margin=0, threshold_cb=None, merge_cb=None)
说明:
1、thresholds是颜色的阈值
2、roi是“感兴趣区”。也就是说只查找对应roi区域是否有对应的色域。roi的格式是(x, y, w, h)的tupple.
3、x_stride 就是查找的色块的x方向上最小宽度的像素,默认为2,如果你只想查找宽度10个像素以上的色块,那么就设置这个参数为10
4、y_stride 就是查找的色块的y方向上最小宽度的像素,默认为1,如果你只想查找宽度5个像素以上的色块,那么就设置这个参数为5
5、invert 反转阈值,把阈值以外的颜色作为阈值进行查找
6、area_threshold 面积阈值,如果色块被框起来的面积小于这个值,会被过滤掉
7、pixels_threshold 像素个数阈值,如果色块像素数量小于这个值,会被过滤掉
8、merge 合并,如果设置为True,那么合并所有重叠的blob为一个
9、margin 边界,如果设置为1,那么两个blobs如果间距1一个像素点,也会被合并。
example:img.find_blobs([red],merge=True)
10、返回值:blobs = img.find_blobs([red])。这里用到了python对象的知识
这是一个用最小二乘法线性回归实现的直线拟合函数。。然而,这种方法对于任何具有很多(或者甚至是任何)异常点的图像都是不好的,这会破坏线条拟合.。所以我们就要自己处理对一些特殊的点进行处理咯。啊,哈哈哈哈。
返回值:
函数返回回归后的线段对象line,有x1(), y1(), x2(), y2(), length(), theta(), rho(), magnitude()参数。x1 y1 x2 y2分别代表线段的两个顶点坐标,length是线段长度,theta是线段的角度。magnitude表示线性回归的效果,它是(0,+∞)范围内的一个数字,其中0代表一个圆。如果场景线性回归的越好,这个值越大。
为什么会这样写呢?因为在慢慢去接触这个领域,就想养成一个好的习惯(尤其是在接触到神经网络之后),尝试去做一些可以泛化或者类似于算法的东西(当然用数学知识自我设计算法的能力打算去研究生培养)。
def Sensor_Init():
sensor.reset() #初始化感光元件
sensor.set_pixformat(sensor.RGB565) #设置色彩空间(sensor.GRAYSCALE: 灰度,每个像素8bit。)
sensor.set_framesize(sensor.QQVGA) #设置图像大小160*120(sensor.QQQVGA) 80*60
sensor.set_auto_gain(False) #在颜色追踪时,关闭自动增益
sensor.set_auto_whitebal(False) #在颜色追踪时,关闭白平衡
sensor.skip_frames(time = 2000) #跳过2000帧
用于stm32和openmv串口通信
uart = UART(3, 115200) #初始化串口3 波特率 = 115200
uart.init(115200,bits=8,parity=None,stop=1)# 8位数据位, 无校验位, 1位停止位
寻找色块,肯定要计算openmv和色块的距离啦,不然会撞飞的。
然后我们就根据官网进行一波推导,下面是推导过程(字丑,莫怪)。
def Coordinates_Distance(width, hight): #计算到物体的距离
Average_R = (width + hight)/2 #计算物体的平均半径
Distance = int(Distance_K/Average_R)
#print(Distance)
return Distance
说一下操作,在这里我把色块放在距离镜头20cm的地方,然后打印出色块在x方向的宽度,也就是blob.w(),则A = blob.w()*20. 也就是Distance_K就得到了。
要找到色块,肯定是要有夹角的啦。
当然也是推理一波咯,知其然知其所以然,哼开玩笑。
tana = D*K.这是结论。没错,所以,还是反向推理,由于场地和焦距限制,我将a取为20的tan(20)= 0.3639.通过然后计算像素点到中心点的距离也就是D。得出D = 56.0357,。那么最后为啥直接取K = 20/56.0357呢?你猜!!!
def Coordinates_Angle(cx, cy): #计算夹角
Intermediate_Variable = (cx-80)*(cx-80) + (cy-60)*(cy-60) #中间变量
Distance_From_Center = math.sqrt(Intermediate_Variable) #开根号计算到中点的距离
#print(Distance_From_Center)
Angle = int(Distance_From_Center*Angle_K)
print(Angle)
return Angle
直接上代码
def Find_Blobs(img): #寻找图片中的颜色
global Distance_Result, Angle_Result
blobs = img.find_blobs(Threshold, area_threshold = 10, merge=True) #调用find_blobs,查找色域
if(blobs):
for blob in blobs:
img.draw_rectangle(blob.rect(), thickness = 2, fill = False) #fill表示不填充矩形
#print(blob.w())
Angle_Result = Coordinates_Angle(blob.cx(), blob.cy())
Distance_Result = Coordinates_Distance(blob.w(), blob.h())
Tx_Date(Angle_Result, Distance_Result)
参考:https://singtown.com/openmv/
author:chen
引用一句话:前人栽树,后人乘凉。生命不止,奋斗不息。