复制图片中的文字-实现逻辑
发表于:2024-06-07 |

前言

这里介绍将我们的图片进行OCR识别之后该如何处理(我简单讲解一下思路,还有很多优化的空间),至于OCR这块是后端的逻辑,要一定的算法,我没那个能力,就不献丑了,大家如果作为一个前端也想尝试一下的话可以使用tesseract.js去做一下,我试过中文的识别效果很一般,而且新的版本都要有梯子才能直接使用,不然都要本地部署。

准备素材

我这里准备了一张图片
ocr识别素材;

得到文字位置数据

这里我用接口得到了我需要的数据,json格式如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
{
"Response": {
"DocumentRecognizeInfo": [
{
"Angle": 0,
"Elements": [
{
"Elements": null,
"Index": 0,
"InsetImageName": "",
"Level": 0,
"Polygon": {
"LeftBottom": {
"X": 116,
"Y": 591
},
"LeftTop": {
"X": 116,
"Y": 550
},
"RightBottom": {
"X": 487,
"Y": 591
},
"RightTop": {
"X": 487,
"Y": 550
}
},
"Text": "陪伴是最长情的告白",
"Type": "title"
},
{
"Elements": null,
"Index": 1,
"InsetImageName": "",
"Level": 0,
"Polygon": {
"LeftBottom": {
"X": 112,
"Y": 617
},
"LeftTop": {
"X": 112,
"Y": 589
},
"RightBottom": {
"X": 496,
"Y": 617
},
"RightTop": {
"X": 496,
"Y": 589
}
},
"Text": "Accompany is the longest confession of love",
"Type": "paragraph"
},
{
"Elements": null,
"Index": 2,
"InsetImageName": "",
"Level": 0,
"Polygon": {
"LeftBottom": {
"X": 292,
"Y": 712
},
"LeftTop": {
"X": 292,
"Y": 673
},
"RightBottom": {
"X": 654,
"Y": 712
},
"RightTop": {
"X": 654,
"Y": 673
}
},
"Text": "守护是最沉默的陪伴",
"Type": "title"
},
{
"Elements": null,
"Index": 3,
"InsetImageName": "",
"Level": 0,
"Polygon": {
"LeftBottom": {
"X": 316,
"Y": 746
},
"LeftTop": {
"X": 316,
"Y": 716
},
"RightBottom": {
"X": 639,
"Y": 746
},
"RightTop": {
"X": 639,
"Y": 716
}
},
"Text": " Guard is the most silent company",
"Type": "paragraph"
}
],
"Height": 828,
"OriginHeight": 828,
"OriginWidth": 828,
"PageNumber": 1,
"RotatedAngle": 0,
"Width": 828
}
],
"InsetImagePackage": null,
"MarkdownBase64": "IyMg6Zmq5Ly05piv5pyA6ZW/5oOF55qE5ZGK55m9CgpBY2NvbXBhbnkgaXMgdGhlIGxvbmdlc3QgY29uZmVzc2lvbiBvZiBsb3ZlCgojIyDlrojmiqTmmK/mnIDmsonpu5jnmoTpmarkvLQKCiBHdWFyZCBpcyB0aGUgbW9zdCBzaWxlbnQgY29tcGFueQoK",
"RequestId": "4ae48612-73ae-4dcb-964c-d237dd334355"
}
}

思路

将图片作为背景图,在上面覆盖一层div,div中是OCR定位得到的文字内容

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<template>
<div
class="img-container"
:style="{ width: imgInfo.width + 'px', height: imgInfo.height + 'px' }"
></div>
</template>
<script setup>
import { ref, reactive } from "vue";
import { FAKE_DATA } from "./fake";

// vue3导入图片
const ocrImg = new URL("@/assets/use.png", import.meta.url).href;
// 图片宽高
const imgInfo = reactive({
width: 0,
height: 0,
});
// 创建img对象
const img = new Image();
// 图片加载完成后
img.onload = () => {
// 设置div的宽高
imgInfo.width = img.width;
imgInfo.height = img.height;
// 根据OCR数据绘制边框
FAKE_DATA.Response.DocumentRecognizeInfo[0].Elements.forEach((item) => {
const el = document.createElement("div");
el.style.position = "absolute";
const { LeftBottom, LeftTop, RightBottom, RightTop } = item.Polygon;
el.style.left = LeftTop.X + "px";
el.style.top = LeftTop.Y + "px";
el.style.width = RightTop.X - LeftTop.X + 15 + "px";
el.style.height = RightBottom.Y - RightTop.Y + "px";
// el.style.border='1px solid red'
el.style.flexGrow = 1;
el.style.fontSize =
item.Type === "title"
? RightBottom.Y - RightTop.Y + "px"
: RightBottom.Y - RightTop.Y - 10 + "px";
el.style.lineHeight =LeftBottom.Y - LeftTop.Y + "px";
el.innerText = item.Text;
el.style.color = "rgba(255,255,255,0)";
el.style.textAlign = "center";
document.querySelector(".img-container").appendChild(el);
});
};
// 图片加载地址
img.src = ocrImg;
</script>
<style>
* {
margin: 0;
padding: 0;
}
.img-container {
background-image: url("@/assets/use.png");
background-size: 100% 100%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
</style>

代码讲解

这里的FAKE_DATA就是那个json,然后我根据json,将文字进行了定位,这时候有个问题就是font-size怎么处理,我这里按照和接口规定的方式处理了,其实大家可以用我之前讲过的方式,计算文字宽度。一点点将font-size给增加,看看文字的高度或者宽度是否超出了父元素的宽高,就可以得到适配的文字大小了

效果

此时的效果就有了,这时候按下cv就可以实现复制粘贴

改进

这里我也有思考过,这个选中效果怎么处理的和微信一样,就是只有边框选中,而不是看起来那么假的选中,我暂时没想到什么好的办法,可能人家用的复制图片里面的文字的方法也不是我这种吧,回头再继续研究一下。如果有能实现出来的小伙伴,麻烦教我一下,我学习一下思路,万分感谢。

结语

端午节要到了,提前祝大家端午节快乐~~~

上一篇:
【可视化学习】63-从入门到放弃WebGL(一)
下一篇:
【可视化学习】62-3D开发中你应该掌握的数学知识(二)