fls 发表于 2020-2-29 11:24

通过cv2搜索某图片中的指定要素

## 背景
应某个老友的要求,想要从一个图片中,搜索出指定的图片元素。
因为当前正好在学习CV方面的知识,所以感觉这个需求比较有趣,所以研究了一下。
## 正文
查了下cv2库的这方面资料,有个matchTemplate模板匹配的方法,通过cv2的归一化相关系数匹配法(TM_CCOEFF_NORMED),来从原图片中匹配到目标图片。
然后通过numpy.where来筛选出图片中符合条件的部分(矩阵元素)的坐标。
*关于cv2的安装或者基本引用等方法,就不在这里述说了*。本文适合用过一次以上的python`opencv-python`库的小伙伴。
### 1.首先打开图片,这里统一进行了一步去色的处理:
```python
# 1.读入原图和模板
img_src = Image.open("main2.jpg")
img_src_gray = np.asarray(img_src.convert('L')) # 黑白
img_src = cv2.cvtColor(np.asarray(img_src), cv2.COLOR_RGB2BGR)
# 目标图
img_aim = np.asarray(Image.open("aim2.jpg").convert('L'))
```
### 2.cv2模板匹配
```python
# 2.模板匹配.cv2.TM_CCOEFF_NORMED=归一化相关系数匹配法.也可采用TM_CCORR_NORMED-归一化相关匹配法
res = cv2.matchTemplate(img_src_gray, img_aim, cv2.TM_CCOEFF_NORMED)
```
### 3.获取匹配后的坐标
```python
# 3.匹配程度大于THRESHOLD阈值坐标.格式y,x
loc = np.where(res >= THRESHOLD)
```
### 4.遍历结果,并显示
```python
# 目标的高、宽
aim_h, aim_w = img_aim.shape[:2]
# 4.遍历符合条件的img数组
# 利用 * 号操作符,可以将元组解压为列表
for point_ in zip(*loc[::-1]): # 倒序,对应着转为x,y的坐标
    # 按目标的高、宽,做标记
    flag_point = (point_ + aim_w, point_ + aim_h)
    # 绘制矩形框:cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
    # 绘制矩形框-参数:img是原图;(x,y)是矩阵的左上点坐标;(x+w,y+h)是矩阵的右下点坐标;(0,255,0)是画线对应的rgb颜色;2是所画的线的宽度
    x1 = cv2.rectangle(img_src, point_, flag_point, (0, 0, 255), 2)

# 显示结果图片
cv2.imshow('out', x1)
cv2.waitKey(0)
```

原图:

!(//www.darkripples.com/blog_resources/static/images/blog_attrs/20190320/search_pic_main.jpg)

目标图:

!(//www.darkripples.com/blog_resources/static/images/blog_attrs/20190320/search_pic_aim.jpg)

效果图:
   
!(//www.darkripples.com/blog_resources/static/images/blog_attrs/20190320/search_pic_rs.jpg)

## 总结
* `cv2.matchTemplate`匹配的使用:
1. CV_TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
2. CV_TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
3. CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
4. CV_TM_SQDIFF_NORMED 归一化平方差匹配法
5. CV_TM_CCORR_NORMED 归一化相关匹配法
6. CV_TM_CCOEFF_NORMED 归一化相关系数匹配法
*python基础:`zip`中利用 * 号操作符,可以将元组解压为列表,这个之前用的不多,所以蛮有新鲜感;
*`numpy.where(condition, x, y)`的使用:满足条件(condition),输出x,不满足则输出y。emmm话说对numpy还没系统学习过,只是用到了什么就记下来;
* 另外,稍微思考了下,想起之前见过的一个连连看类型的游戏外挂,用的是切割图片,来完全匹配,然后判断是否可进行连接等等;
想来可以基于此方式来实现优化;可以直接检测目标图片的坐标,暴力找到其匹配的另一个图片,也无需判断是否可连接,直接移动鼠标强制点击连接~
页: [1]
查看完整版本: 通过cv2搜索某图片中的指定要素