Skip to content

Commit

Permalink
特征匹配
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhaoZuohong committed Jul 14, 2024
1 parent 7619b8c commit 8738a9d
Show file tree
Hide file tree
Showing 4 changed files with 489 additions and 10 deletions.
4 changes: 2 additions & 2 deletions _includes/common/mathjax.liquid
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{%- if page.content contains "$$" -%}
{%- if page.content contains "$" -%}
<script>
window.MathJax = {% if site.mathjax %}{{ site.mathjax | jsonify }}{% else %}{}{% endif %};
window.MathJax = { tex: { inlineMath: [["$", "$"]] } };
</script>
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax/es5/tex-svg-full.js"></script>
{%- endif %}
10 changes: 4 additions & 6 deletions _includes/feature-matching.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<div class="highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">cv2</span>
<span class="kn">from</span> <span class="nn">matplotlib</span> <span class="kn">import</span> <span class="n">pyplot</span> <span class="k">as</span> <span class="n">plt</span>
<span class="kn">from</span> <span class="nn">arknights_mower.utils.image</span> <span class="kn">import</span> <span class="n">loadimg</span>
<span class="kn">from</span> <span class="nn">arknights_mower.utils.matcher</span> <span class="kn">import</span> <span class="n">ORB</span><span class="p">,</span> <span class="n">flann</span>
<span class="kn">from</span> <span class="nn">arknights_mower.utils.matcher</span> <span class="kn">import</span> <span class="n">GOOD_DISTANCE_LIMIT</span><span class="p">,</span> <span class="n">ORB</span><span class="p">,</span> <span class="n">flann</span>
</pre></div>
</div>
</div>
Expand All @@ -33,7 +33,7 @@
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre><span class="ansi-white-fg">2024-07-13 19:59:06,194 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Documents/hot_update/hortus/terminal.jpg</span>
<pre><span class="ansi-white-fg">2024-07-14 11:28:16,539 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Documents/hot_update/hortus/terminal.jpg</span>
</pre>
</div>
</div>
Expand Down Expand Up @@ -73,7 +73,7 @@
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre><span class="ansi-white-fg">2024-07-13 19:59:06,644 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Documents/mower-profile/screenshot/501/20240705031952.png</span>
<pre><span class="ansi-white-fg">2024-07-14 11:28:16,986 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Documents/mower-profile/screenshot/501/20240705031952.png</span>
</pre>
</div>
</div>
Expand All @@ -98,7 +98,6 @@
<div class="inner_cell">
<div class="input_area">
<div class="highlight hl-ipython3"><pre><span></span><span class="n">matches</span> <span class="o">=</span> <span class="n">flann</span><span class="o">.</span><span class="n">knnMatch</span><span class="p">(</span><span class="n">des1</span><span class="p">,</span> <span class="n">des2</span><span class="p">,</span> <span class="n">k</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">GOOD_DISTANCE_LIMIT</span> <span class="o">=</span> <span class="mf">0.7</span>
<span class="n">good</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="n">matches</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len_pair</span> <span class="o">:=</span> <span class="nb">len</span><span class="p">(</span><span class="n">pair</span><span class="p">))</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
Expand Down Expand Up @@ -189,7 +188,7 @@
<div class="output_area">
<div class="prompt"></div>
<div class="output_subarea output_stream output_stdout output_text">
<pre><span class="ansi-white-fg">2024-07-13 19:59:08,194 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Documents/mower-profile/screenshot/501/20240705071219.png</span>
<pre><span class="ansi-white-fg">2024-07-14 11:28:18,374 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Documents/mower-profile/screenshot/501/20240705071219.png</span>
</pre>
</div>
</div>
Expand All @@ -214,7 +213,6 @@
<div class="inner_cell">
<div class="input_area">
<div class="highlight hl-ipython3"><pre><span></span><span class="n">matches</span> <span class="o">=</span> <span class="n">flann</span><span class="o">.</span><span class="n">knnMatch</span><span class="p">(</span><span class="n">des1</span><span class="p">,</span> <span class="n">des2</span><span class="p">,</span> <span class="n">k</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="n">GOOD_DISTANCE_LIMIT</span> <span class="o">=</span> <span class="mf">0.7</span>
<span class="n">good</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="n">matches</span><span class="p">:</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len_pair</span> <span class="o">:=</span> <span class="nb">len</span><span class="p">(</span><span class="n">pair</span><span class="p">))</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
Expand Down
441 changes: 441 additions & 0 deletions _includes/matcher.html

Large diffs are not rendered by default.

44 changes: 42 additions & 2 deletions dev/feature-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sort: 5

## 特征与特征点

可以直接使用 `arknights_mower.utils.matcher` 中的 `ORB` 提取特征点
`arknights_mower.utils.matcher` 中的 `ORB` 可用于提取特征点

一般而言,在图像中,拐角、复杂的图案与纹理(包括文字)处可以提取到较多的特征点;在空白处,很难或无法提取到特征点。从复杂的图像中可以提取到更多的特征点。

Expand All @@ -19,9 +19,49 @@ sort: 5

## 特征点的匹配

可以直接使用 `arknights_mower.utils.matcher` 中的 `flann` 对特征点进行匹配。
`arknights_mower.utils.matcher` 中的 `flann` 可用于匹配特征点。

对于目标图像中的每个特征点 $A$,使用 `flann.knnMatch(k=2)`找出截图中与之距离最近的和第二近的两个特征点 $B_1$、$B_2$. 如果 $A$ 与 $B_1$ 的距离 $\text{d}(A, B_1)$ 和 $A$ 与 $B_2$ 的距离 $\text{d}(A, B_2)$ 的比值小于 `GOOD_DISTANCE_LIMIT`,就认为 $A$ 与 $B_1$ 是一对“好”的匹配。

下面的例子展示了如何利用特征匹配在终端页面定位活动入口。

<details>
<summary>使用示例</summary>
{% include feature-matching.html %}
</details>

## 利用特征匹配定位目标图像

`arknights_mower.utils.matcher` 中的 `Matcher` 类可用于定位目标图片。

实例化 `Matcher` 类时,需传入灰度图像 `origin`。实例化过程中计算 `origin` 图像的特征点。

`Matcher` 类的实例方法 `match()` 接受 6 个参数,其中 `query` 必选:

- `query`:灰度目标图像;
- `draw`:控制是否绘制并显示匹配过程;
- `scope``origin` 的特征点中,在此区域内的特征点参与匹配;
- `dpi_aware`:大部分元素的尺寸不变,`dpi_aware` 默认为 `False`,若匹配结果与目标图像的尺寸相差较大时拒绝结果。对于尺寸有变化的元素,将此选项设置为 `True`
- `prescore`:SSIM 分数阈值。如果此参数为正,则根据 SSIM 分数决定是否接受匹配结果。
- `judge`:在 `prescore` 为 0 时生效。如果为 `True`,则使用支持向量机判断是否接受匹配结果,否则直接接受匹配结果。

如果匹配成功,`match()` 返回目标图片在截图中匹配到的区域;否则返回 `None`

<details>
<summary>使用示例</summary>
{% include matcher.html %}
</details>

## 注意事项

### 性能

从截图提取特征点一般会花费数十毫秒,一次 FLANN 匹配也会花费十几毫秒到几十毫秒。大量使用特征匹配会导致脚本很慢。

### 目标图像截取

目标图像应尽量满足特征点数量多、尺寸小、与其它目标图像有较大区别。例如对于按钮,只截取按钮中独特的图案,或在文字中截取 3-5 字的关键词,相比截取整个按钮,往往能得到更好的效果。

### 随机性

FLANN 和 RANSAC 算法具有一定的随机性。若结果变化较大,可考虑重新截取目标图像,或换用其它匹配方式。

0 comments on commit 8738a9d

Please sign in to comment.