size_categories:100K<n<1M language:zh art region:us
@dataset{early_media,
  author       = {Xing Tian},
  title        = {wechat_or_qq_icon_detection},
  month        = aug,
  year         = 2023,
  publisher    = {Xing Tian},
  version      = {1.0},
}
---
language:
- zh
tags:
- art
size_categories:
- 100K<n<1M
---
## WeChat 或 QQ 图标检测.

任务: 从图像中检测出 WeChat 或 QQ 图标的位置.

方法: 基于 OpenCV 库, 通过 SIFT 或 SURF 图像特征作检测. 

```text
由于 SURF 和 SIFT 算法有专利限制, 
其安装环境是: 
python==3.6.5
opencv-contrib-python==3.4.2.16

由于 huggingface 的 space 中的 python 为 3.10 版本, 已无法安装此 opencv 库. 

你也可以在这里找到相关代码, 但这个库已经不再维护了. 

https://github.com/tianxing1994/OpenCV/
dir: 练习实例 -> SIFT_SURF 图像特征作目标检测(在图片中检测出 QQ 图标的位置)

因此将实现方法记录如下: 

```

实现步骤:

(1)采用 opencv 库的 SIFT 或 SURF 图像特征 `cv.xfeatures2d.SIFT_create()` 对目标区域生成特征点向量.

(2)为减少特征点数量, 对所有的特征点向量做聚类, 将聚类中心作为特征点, 得到 `template_descriptors`.

(3)计算目标图像中的所有 SIFT 或 SURF 图像特征点. 得到 `scene_descriptors`.

(4) 采用 `flann.knnMatch` 方法进行特征点匹配, (如果最近匹配距离比第二匹配距离的 0.7 倍还要小, 则认为这个点是 `good_match`, 即认为好的特征点具有独特征, 不会有其它更相似的点).

(5)最小要有3个 `good_match` 才认为图标匹配成功.

(6)最后根据 `good_match` 点的分布计算图标的中心, 我的做法是计算点集中心和平均距离, 将大于平均距离的点丢弃, 重复此过程, 直到半径小于阈值.


涉及到的方法有:
```python
import cv2 as cv

sift = cv.xfeatures2d.SIFT_create()

index_params = dict(algorithm=0, trees=5)
search_params = dict(checks=50)
flann = cv.FlannBasedMatcher(index_params, search_params)

keypoints, descriptors = sift.detectAndCompute(image, None)

matches = flann.knnMatch(
    queryDescriptors=template_descriptors,
    trainDescriptors=scene_descriptors,
    k=2
)

good_matches = []
for m, n in matches:
    if m.distance < 0.7 * n.distance:
        good_matches.append(m)

k = 3
if len(good_matches) > k:
    print(good_matches)
else:
    print("Not enough matches are found - %d/%d" % (len(good_matches), k))


```

参考链接:
```text
https://docs.opencv.org/3.0-beta/index.html
```

bbox 对应类别 category 的文字为:
```text
CATEGORIES = [
    "红黑白QQ图标", "绿边白色微信图标", "淡蓝底全白QQ图标",
    "绿底全白微信图标", "大绿小白微信图标", "纯色微信图标", "纯色QQ图标"
]
```
