下面只有openmv的代码,其实第一个云台的思路很简单,而且分为两种方式
第一种方式就是云台盲打,这里所谓的盲打就是云台要有较高的精度,且需要将云台的角度对应到幕布的坐标系,比如说我需要打(25,25)的位置那么云台就应该转到对应的俯仰角度,接着openmv识别矩形的四个顶点的坐标转换成世界坐标系(就是幕布的坐标系)发送到云台,云台开环打这些点。
我测试了,这种方法在云台精准的情况下,且openmv的摄像头没有过多畸变的情况下是可以实现的
第二种方法是闭环打
所谓的闭环打就是摄像头既要识别边框也要识别红色的点,然后把边框分为很多N点,这些N个点就是红色激光的目标,当红色激光到达一个目标的时候就前往下一个以此能够环形的打这些点。
下面贴下对应的代码,不对代码做过的解释,有需要的可以私我,我把stm32对应的代码发给你们。
后面把代码都整理一下,会陆陆续续发出来。
import sensor
import image
import time, pyb
import struct
from pyb import UART
import math
# 初始化摄像头
sensor.reset()
# 设置摄像头像素格式为RGB565(也可以设置为灰度但是颜色识别就无法使用了)
sensor.set_pixformat(sensor.RGB565)
# 设置摄像头像素大小为QVGA(320x240)
sensor.set_framesize(sensor.QQVGA)
led = pyb.LED(3) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4.
uart = UART(3, 115200)
# 假设你已经得到了幕布中心和正方形四个顶点在像素坐标系中的坐标
center_pixel_coord = (81, 57)
square_pixel_coords = [(40, 10), (124, 12), (123,10), (36, 97)]
# 计算像素坐标系中的正方形的宽度和高度
pixel_width = max(coord[0] for coord in square_pixel_coords) - min(coord[0] for coord in square_pixel_coords)
pixel_height = max(coord[1] for coord in square_pixel_coords) - min(coord[1] for coord in square_pixel_coords)
# 计算像素单位到幕布单位(cm)的映射比例
pixel_to_cm_ratio_x = 50.0 / pixel_width
pixel_to_cm_ratio_y = 50.0 / pixel_height
# 定义一个函数,将像素坐标转换为幕布坐标
def pixel_to_physical(pixel_coord):
pixel_x, pixel_y = pixel_coord
center_x, center_y = center_pixel_coord
physical_x = (pixel_x - center_x) * pixel_to_cm_ratio_x
physical_y = -(pixel_y - center_y) * pixel_to_cm_ratio_y+25
return (physical_x, physical_y)
def angle(point, center):
return math.atan2(point[1] - center[1], point[0] - center[0])
def shrink_corner(corner, center, shrink_pixels):
cx, cy = center
x, y = corner
dx = x - cx
dy = y - cy
length = math.sqrt(dx**2 + dy**2)
shrink_x = dx / length * shrink_pixels
shrink_y = dy / length * shrink_pixels
return (x - shrink_x, y - shrink_y)
shrink_pixels = 3
def send_coordinates(coords):
data = b'\xAA' # 帧头
for coord in coords:
x, y = coord
data += struct.pack('ff', x, y)
data += b'\xCC' # 帧尾
uart.write(data)
print((data))
time.sleep(2)
while(True):
img = sensor.snapshot().lens_corr(strength = 0.5, zoom = 1.0)
led.on()
for r in img.find_rects(threshold = 30000):
img.draw_rectangle(r.rect(), color = (255, 255, 255))
# 获取四个角点的坐标
corners = list(r.corners()) # 将元组转换为列表
# 计算四个角点的中心
cx = sum([p[0] for p in corners]) / 4
cy = sum([p[1] for p in corners]) / 4
# 根据每个点相对于中心的角度进行排序
corners.sort(key=lambda p: angle(p, (cx, cy)))
# 在四个角点上画出数字1、2、3和4
for i in range(4):
img.draw_string(corners[i][0], corners[i][1], str(i+1), color=(255, 255, 255), scale=2)
corners = [shrink_corner(corner, (cx, cy), shrink_pixels) for corner in corners]
# 按照顺时针的顺序打印四个角点的坐标
# print(corners)
physical_corners = [pixel_to_physical(corner) for corner in corners]
send_coordinates(physical_corners)
import sensor
import image
import time, pyb
import struct
from pyb import UART
import math
# 初始化摄像头
sensor.reset()
# 设置摄像头像素格式为RGB565(也可以设置为灰度但是颜色识别就无法使用了)
sensor.set_pixformat(sensor.RGB565)
# 设置摄像头像素大小为QVGA(320x240)
sensor.set_framesize(sensor.QQVGA)
led = pyb.LED(3) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4.
uart = UART(3, 115200)
# 假设你已经得到了幕布中心和正方形四个顶点在像素坐标系中的坐标
center_pixel_coord = (81, 57)
square_pixel_coords = [(40, 10), (124, 12), (123,10), (36, 97)]
# 计算像素坐标系中的正方形的宽度和高度
pixel_width = max(coord[0] for coord in square_pixel_coords) - min(coord[0] for coord in square_pixel_coords)
pixel_height = max(coord[1] for coord in square_pixel_coords) - min(coord[1] for coord in square_pixel_coords)
# 计算像素单位到幕布单位(cm)的映射比例
pixel_to_cm_ratio_x = 50.0 / pixel_width
pixel_to_cm_ratio_y = 50.0 / pixel_height
# 定义红色的阈值,这个阈值可能需要根据实际的环境进行调整
red_threshold = (1, 94, 104, 22, -100, 52)
#(38, 88, 90, 29, -91, 85)
# 定义一个函数,将像素坐标转换为幕布坐标
def pixel_to_physical(pixel_coord):
pixel_x, pixel_y = pixel_coord
center_x, center_y = center_pixel_coord
physical_x = (pixel_x - center_x) * pixel_to_cm_ratio_x
physical_y = -(pixel_y - center_y) * pixel_to_cm_ratio_y+25
return (physical_x, physical_y)
def angle(point, center):
return math.atan2(point[1] - center[1], point[0] - center[0])
shrink_pixels = 3
def send_coordinates(coords):
data = b'\xAA' # 帧头
for coord in coords:
x, y = coord
data += struct.pack('ff', x, y)
data += b'\xCC' # 帧尾
uart.write(data)
print((data))
def interpolate_points(p1, p2, num_points):#插值函数
x1, y1 = p1
x2, y2 = p2
return [(x1 + i * (x2 - x1) / (num_points - 1), y1 + i * (y2 - y1) / (num_points - 1)) for i in range(num_points)]
shrink_pixels = 3
num_points_per_edge = 20
target_point_index = 0
distance_threshold = 2 # 你需要根据实际情况设置这个值
red_coord =(0,0)
time.sleep(2)
while(True):
img = sensor.snapshot().lens_corr(strength = 0.5, zoom = 1.0)
led.on()
# 在主循环中找到红色光电的坐标
red_blobs = img.find_blobs([red_threshold])
if red_blobs:
max_blob = max(red_blobs, key=lambda b: b.pixels())
img.draw_rectangle(max_blob.rect())
img.draw_cross(max_blob.cx(), max_blob.cy())
red_coord = (max_blob.cx(), max_blob.cy())
for r in img.find_rects(threshold = 30000):
img.draw_rectangle(r.rect(), color = (255, 255, 255))
# 获取四个角点的坐标
corners = list(r.corners()) # 将元组转换为列表
# 计算四个角点的中心
cx = sum([p[0] for p in corners]) / 4
cy = sum([p[1] for p in corners]) / 4
# 根据每个点相对于中心的角度进行排序
corners.sort(key=lambda p: angle(p, (cx, cy)))
# 在四个角点上画出数字1、2、3和4
for i in range(4):
img.draw_string(corners[i][0], corners[i][1], str(i+1), color=(255, 255, 255), scale=2)
all_points = []
for i in range(4):
all_points += interpolate_points(corners[i], corners[(i+1)%4], num_points_per_edge)
if math.sqrt((red_coord[0] - all_points[target_point_index][0])**2 + (red_coord[1] - all_points[target_point_index][1])**2) < distance_threshold:
target_point_index = (target_point_index + 1) % len(all_points)
# 打包数据
data = bytes([0xAA,red_coord[0] >> 8, red_coord[0] & 0xFF, red_coord[1] >> 8, red_coord[1] & 0xFF,
(int)(all_points[target_point_index][0] ) >> 8, (int)(all_points[target_point_index][0] ) & 0xFF,
(int)(all_points[target_point_index] [1]) >> 8, (int)(all_points[target_point_index] [1]) & 0xFF, 0xCC])
# 发送数据
uart.write(data)
print(red_coord,all_points[target_point_index])