# rubik_cube.py
**Repository Path**: xinghee/rubik_cube.py
## Basic Information
- **Project Name**: rubik_cube.py
- **Description**: pyautogui + kociemba | 实现魔方自动还原
- **Primary Language**: Python
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: https://www.wzhecnu.cn/2022/01/28/programming/others/rubik-s-cube/
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2022-06-27
- **Last Updated**: 2023-12-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 魔方
## README
## 基于图像识别的魔方自动还原
在 B 站看到一个用 Python 复原魔方的[视频](https://www.bilibili.com/video/BV12i4y1G74V),觉得还蛮有意思,就自己动手写了个工具git。废话不多说,先看演示吧。
1. 随机打乱一个魔方
2. 导入工具,一行代码还原魔方
```py
from rubik import *
Cube().auto_solve_cube(wait=False)
```
---
## 使用介绍
### 安装依赖
1. 安装 Python 包
```bash
pip install pyautogui # 安装自动化工具
pip install kociemba # 安装魔方工具
```
2. Ubuntu 系统还需安装 scrot,用于截图
```bash
sudo apt-get install scrot
```
3. 搜索安装谷歌浏览器的插件 `Rubik`

### 使用方法
注:`demo/` 目录下提供了用于演示的 Jupyter 文件。
1. 打开浏览器插件,双击进入准备状态

2. 初始化类对象 `Cube`,检测魔方位置
```py
from rubik import *
cube = Cude()
```
3. 查看魔方定位是否正确
```py
cube.show_detection()
```

4. 检查小面位置
```py
cube.check_facets()
```
5. 检查基本旋转
```py
cube.check_basic_moves() # 检查基本旋转是否正确
```
6. 识别魔方状态,并打印展开图
```py
# 获取小面分布信息
state = cube.get_cube_distribution(string_code=True)
print(expand_cube(state))
```
7. 识别并求解魔方
```py
cube.auto_solve_cube()
```
8. 构造给定魔方状态
```py
state = "UBRLUFFUBLRUFRLLLRDBDRFDBBUDDBUDDLRFBFLDLBFFRFLRUBRDUU"
cube.to_cube_state(state)
```
### 文件说明
1. `src` 目录下有四个文件
| 文件名 | 说明介绍 |
| :---: | :-----: |
| `rubik.py` | 类对象 `Cube` |
| `tools.py` | 函数工具 |
| `data.py` | 记录魔方的色块等信息 |
| `scale_match.py` | 支持比例放缩的图像检测 |
2. `demo` 目录下
| 文件名 | 说明介绍 |
| :---: | :-----: |
| `demo.jupyter` | 演示文档 |
| `quick_start.py` | 快捷调用|
---
## 工具原理
分两部分内容:
- `pyautogui + cv2` 检测魔方位置,识别魔方状态,执行电脑操作
- `kociemba` 调用魔方算法
### 原理细节
1. 图像检测,计算最佳比例和魔方位置

2. 计算一点 + 一边,并推导其他位置信息
3. 魔方状态码
- 魔方状态码是 `URFDLB` 构成的字符串,`URFDLB` 是魔方六个面的缩写,其中 U 为顶面(up),R 为右面(right),F 为正面(Front),D 为顶面(down),L 为左面(Left),B 为背面(Back)
- 状态码按如下展开图的标号顺序读入
```python
|************|
|*U1**U2**U3*|
|************|
|*U4**U5**U6*|
|************|
|*U7**U8**U9*|
|************|
************|************|************|************
*L1**L2**L3*|*F1**F2**F3*|*R1**R2**R3*|*B1**B2**B3*
************|************|************|************
*L4**L5**L6*|*F4**F5**F6*|*R4**R5**R6*|*B4**B5**B6*
************|************|************|************
*L7**L8**L9*|*F7**F8**F9*|*R7**R8**R9*|*B7**B8**B9*
************|************|************|************
|************|
|*D1**D2**D3*|
|************|
|*D4**D5**D6*|
|************|
|*D7**D8**D9*|
|************|
```
- 比如还原状态为 `UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB`
4. 识别魔方状态:
- 将正视图的三面视为 `U, L, F`,截图识别颜色分布
- 滑动到背面,获取后三面的颜色分布
- 两部分信息整合,导出魔方状态码
5. 魔方公式
- 调用函数 `kociemba.solve` ,获取魔方公式
- 魔方公式为 `U, U', U2, R, R', R2...` 等构成的列表
- 其中 `U, U', U2` 分别代表顶面顺时针旋转 90°,逆时针旋转 90°,以及旋转旋转 180°,其他各面规则同理
6. 将公式实现为操作
- 由小面位置和基本向量计算位置参数
- 用 pyautogui 的函数 `moveTo` 和 `dragRel` 实现鼠标移动和拖拽
由于函数间需频繁共享位置数据,因而使用面向对象编程,数据作为属性,函数作为方法。
---
## 写在最后
这是放假在家随手写的实战,代码在 Ubuntu 和 Windows 测试通过,如果遇到问题欢迎评论交流~