本文主要介绍opencv里面一些常用的视觉方案,所需的全部代码均在如下
1.给视觉单独开一个进程持续运行并更新全局变量
# 获取并处理图像
def get_image():
while True:
# 开全局变量处理,分理处红绿蓝
global image, image_red, image_green, image_blue
# 从摄像头获取图像
_,image=capture.read()
image_red=image[:,:,2].astype(np.float32)
image_green=image[:,:,1].astype(np.float32)
image_blue=image[:,:,0].astype(np.float32)
#cv2.imshow('image',image)
#cv2.waitKey(1)
# 获取图像单独开进程
get_image_threading = threading.Thread(target=get_image)
get_image_threading.start()
2.图形的映射变换
2.1针对图像的映射
图形的映射变换在视觉中经常使用,而且很容易将点的顺序搞混,一旦搞混很难把顺序重新找回来。我这里是二维的图形变换,可以将指定的二维图像的四个点映射到另外背景图上指定的4个点
# 获取需要变换的原始图像
photo_origin = cv2.imread('photo_origin.jpg')
# 这里我把图形转换为灰度图再进行映射变换
photo_origin=cv2.cvtColor(photo_origin, cv2.COLOR_BGR2GRAY)
# 获取背景图片(即你希望将图片映射到的背景,注意这里的背景图是三色图)
back_ground = cv2.imread('back_ground.jpg')
# 对应原先图像的,左上,左下,右下,右上,四个点(这里的四个点是我之前题目的点,你要更换成你自己的,下同)
pts0=np.float32([[63,165],[413,116],[413,562],[53,502]])
# 建立映射需要的一一对应(这个顺序是定死了的)
pts1=np.float32([[pts0[0][1],pts0[0][0]],[pts0[3][1],pts0[3][0]],[pts0[2][1],pts0[2][0]],[pts0[1][1],pts0[1][0]]])
# 对应映射后图像,左上,左下,右下,右上,四个点(记得更换为你自己的点)
pts2=np.float32([[0,0],[968,0],[968,968],[0,968]])
# 生成最为关键的变换矩阵
M = cv2.getPerspectiveTransform(pts1,pts2)
# 变换后的图形(这里注意,你的变换后的图像背景是全黑的,需要用cv2.add函数将图像和另一图像相结合)
photo_trans = cv2.warpPerspective(photo_origin,M,(back_ground.shape[1],back_ground.shape[0]))
show_image(photo_trans)
2.2针对某一个点的映射
这里是让我们单独把原来图像中的某一个点映射到变换后图像上的点,这样就避免了反复地把图像进行整体的映射变换,而只需对一个点进行操作
# 这里的M就是前面已经计算出来的M矩阵(建议保存后这里就可以直接导入)
M=np.load('M.npy')
# 这里的point_origin就是要准备变换的原来的点
def trans_point(point_origin):
global point_trans
try:
point2=np.array([point_origin[1],point_origin[0],1])
# 这里相当于是把一个单点给映射变换过去了
point3=np.dot(M,point2)
# point_trans就是变换后的点
point_trans=[point3[1]/point3[2],point3[0]/point3[2]]
except:
point_trans=point_trans
return point_trans
3.模式匹配并获取目标位置坐标
注意:模式匹配寻找目标图形的精度不高,要求照片里的图像与给的目标图像极为相似才能匹配成功,而且模式匹配是针对灰度图的识别,所以不能区分颜色。所以一般需要现将照片先处理一下,比如突出某种颜色或者过滤一些噪点后再使用,可能效果会更好
# 模式匹配获取目标位置,这里都统一采用灰度图
# 这个是目标图像
aim_image = cv2.imread('aim.png')
# 这个是目标图像的灰度图
aim_gray = cv2.cvtColor(aim_image, cv2.COLOR_BGR2GRAY)
threshold = 0.8
def get_aim_point(aim_gray,image_gray):
global aim_center
try:
result = cv2.matchTemplate(image_gray, aim_gray, cv2.TM_CCOEFF_NORMED)
locations = np.where(result >= threshold)
# 转换为(x, y)坐标
locations = list(zip(*locations[::-1]))
# 转换为目标中心点坐标
aim_center=np.array([int(locations[0][1] + aim_image.shape[0] / 2),int(locations[0][0] + aim_image.shape[1] / 2)])
except:
aim_center=aim_center
return(aim_center)
4.突出图像中的红色部分,其余部分都过滤掉(配合前面的视觉线程使用,蓝色和绿色同理)
# 突出图像中的红色目标
def get_red():
global image, image_red, image_green, image_blue
image_red_only=image_red*2-image_blue-image_green
image_red_only[image_red_only<0]=0
return image_red_only
5. 拍照,保存一张照片(图片类型为.jpg)
# 拍照,保存一张照片
def take_photo(photo_name):
global capture
photo_name=photo_name+'.jpg'
_,image=capture.read()
cv2.imwrite(photo_name,image)
print('take photo success')
6.用matplotlib展示一张numpy数据类型的图片
这里注意一下,用opencv保存的图片与matplotlib展示图片时,红色与绿色色素似乎是反过来的
# 展示图片
def show_image(image):
image_show=image.astype(np.uint8)
plt.imshow(image_show, cmap='gray')
plt.axis('off') # 不显示坐标轴
plt.show()
本文章持续更新中,有不足或者遗漏的地方还望多多指正
标签:树莓,映射函数,photo,image,point,cv2,aim,opencv,图像 From: https://blog.csdn.net/qq_57837641/article/details/141197643