ROS相机/视觉学习(python)
·
**和cpp不同,py是在终端添加可执行权限
ljy@ljy-Y7000P:~/camera_ws/src$ cd image_package_py/scripts/
ljy@ljy-Y7000P:~/camera_ws/src/image_package_py/scripts$ ls
image_node.py
ljy@ljy-Y7000P:~/camera_ws/src/image_package_py/scripts$ chmod +x image_node.py
ljy@ljy-Y7000P:~/camera_ws/src/image_package_py/scripts$ ls
image_node.py
ljy@ljy-Y7000P:~/camera_ws/src/image_package_py/scripts$
rosrun的也直接是文件名,而不是cmake文件可执行权限那命名的node
仿真实现
一、ros相机图像获取实现
机器人头部相机-->ros的 sensor_msgs::Image格式--cv_bridge-->OpenCV的 Mat格式
想要显示图像,可以通过cv2.image()
这一块基本上是固定流程
#!/usr/bin/env python3
# coding=utf-8
#上面两个分别是为了说明编译器和显示中文添加的
import rospy
import cv2
from sensor_msgs.msg import Image # 引入image消息格式
from cv_bridge import CvBridge,CvBridgeError
def Cam_RGB_Callback(msg):
bridge = CvBridge()
try:
cv_image = bridge.imgmsg_to_cv2(msg,"bgr8") #注意是bgr8
except CvBridgeError as e:
rospy.logerr("格式转换错误:%s",e)
return
cv2.imshow("RGB",cv_image) # 分别是显示框的标题,和显示的图像
cv2.waitKey(1) # 暂停1ms等待imshow完成工作
if __name__ == "__main__":
rospy.init_node("show_cv_image") #注意节点名不能重复
# 订阅kinect2相机话题,Image消息类型,回调函数为Cam_RGB_Callback
rgb_sub = rospy.Subscriber("/kinect2/qhd/image_color_rect",Image,Cam_RGB_Callback,queue_size=10)
#spin让主函数阻塞处于等待
rospy.spin()
二、颜色识别与定位
这里在前面的基础上,增加了对cv图像的处理。
*Python 写 ROS 图像节点时,回调函数尽量短。回调里只存数据,不要做太重的图像处理,更不要长时间卡在循环里。在回调函数里进行遍历可能导致程序卡住。
(1)颜色空间转换RGB --> HSV
(2)二值化分割提取目标物
(3)计算得出目标物质心坐标
#!/usr/bin/env python3
# coding=utf-8
import rospy
import cv2
from sensor_msgs.msg import Image
from cv_bridge import CvBridge,CvBridgeError
h_min = 10
h_max = 40
s_min = 90
s_max = 255
v_min = 1
v_max = 255
bridge = CvBridge()
image = None
def Cam_RGB_Callback(msg):
global h_min,h_max,s_min,s_max,v_min,v_max
global image
try:
image = bridge.imgmsg_to_cv2(msg,"bgr8")
except CvBridgeError as e:
rospy.logerr("%s",e)
return
return
def nothing(x):
pass
if __name__ == "__main__":
rospy.init_node("hsv_node",anonymous=True) #增加随即后缀避免重名
rgb_sub = rospy.Subscriber("kinect2/qhd/image_color_rect",Image,Cam_RGB_Callback,queue_size=1)
cv2.namedWindow("Threshold") # 为了能够动态调节增加的窗口,这个不能删掉,因为后面会搜索这个
# 在窗口里创建的滑杆 cv2.createTrackbar(滑杆名字, 窗口名字, 初始值, 最大值, 回调函数)
cv2.createTrackbar("h_min","Threshold",h_min, 179, nothing) #opencv设置h为0-179
cv2.createTrackbar("h_max","Threshold",h_max, 179, nothing)
cv2.createTrackbar("s_min","Threshold",s_min, 255, nothing)
cv2.createTrackbar("s_max","Threshold",s_max, 255, nothing)
cv2.createTrackbar("v_min","Threshold",v_min, 255, nothing)
cv2.createTrackbar("v_max","Threshold",v_max, 255, nothing)
# 这里可以删掉,因为会创建新的
# cv2.namedWindow("RGB")
# cv2.namedWindow("HSV")
# cv2.namedWindow("Result")
rate = rospy.Rate(30) # 表示1s循环30次
while not rospy.is_shutdown():
h_min = cv2.getTrackbarPos("h_min","Threshold") # cv2.getTrackbarPos("滑杆名字", "窗口名字")去这个窗口找数值
h_max = cv2.getTrackbarPos("h_max","Threshold")
s_min = cv2.getTrackbarPos("s_min","Threshold")
s_max = cv2.getTrackbarPos("s_max","Threshold")
v_min = cv2.getTrackbarPos("v_min","Threshold")
v_max = cv2.getTrackbarPos("v_max","Threshold")
cv_image = image.copy() #避免回调和主函数同时处理
# 将rgb转成hsv格式,也是固定格式
hsv_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2HSV)
# HSV空间进行均衡化,全是固定流程
h, s, v = cv2.split(hsv_image)
v = cv2.equalizeHist(v)
hsv_image = cv2.merge([h, s, v])
#使用颜色阈值进行二值化
th_image = cv2.inRange(hsv_image,(h_min,s_min,v_min),(h_max,s_max,v_max))
# 开操作 (去除一些噪点)
element = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
th_image = cv2.morphologyEx(th_image, cv2.MORPH_OPEN, element)
# 闭操作 (连接一些连通域)
th_image = cv2.morphologyEx(th_image, cv2.MORPH_CLOSE, element)
# #遍历图像寻找并标记目标点(遍历可能导致太慢,参考下面处理)
# target_x,target_y,p_count = 0,0,0
# img_h,img_w = th_image.shape[:2] #shape是(高,宽,通道数)
# #注意图像高在前
# for y in range(img_h):
# for x in range(img_w):
# if th_image[y,x] == 255:
# p_count +=1
# target_x +=x
# target_y +=y
# if p_count>0:
# target_x = target_x//p_count
# target_y = target_y//p_count
# #cv2.line(图像, 起点, 终点, 颜色, 线宽) 颜色是bgr
# cv2.line(cv_image,(target_x-10,target_y),(target_x+10,target_y),[255,0,0],2)
# cv2.line(cv_image,(target_x,target_y-10),(target_x,target_y+10),[255,0,0],2)
# print("数量",p_count)
# else:
# print("没有目标颜色")
# th_image 是这个格式的,0 表示黑色,不是目标颜色,255 表示白色,是目标颜色
# 0 0 0 0 0
# 0 255 255 255 0
# 0 255 255 255 0
# 0 0 0 0 0
# M 是一个字典,m00:白色区域的总量;m10:所有白色像素的 x 坐标加权总和;m01:所有白色像素的 y 坐标加权总和
M = cv2.moments(th_image)
if M["m00"] > 0:
target_x = int(M["m10"] / M["m00"])
target_y = int(M["m01"] / M["m00"])
p_count = int(M["m00"] / 255)
cv2.line(cv_image, (target_x - 10, target_y), (target_x + 10, target_y), (255, 0, 0), 2)
cv2.line(cv_image, (target_x, target_y - 10), (target_x, target_y + 10), (255, 0, 0), 2)
print("数量", p_count)
else:
print("没有目标颜色")
cv2.imshow("RGB",cv_image)
cv2.imshow("HSV",hsv_image)
cv2.imshow("Result",th_image)
cv2.waitKey(5)
rate.sleep()
cv2.destroyAllWindows() #程序结束时,关闭所有窗口
深度相机实现
更多推荐

所有评论(0)