【技术分享】Python3 图片转文字服务
2023-06-05 / 0 评论 / 125 阅读 / 8 点赞

【技术分享】Python3 图片转文字服务

发光的神
2023-06-05 / 0 评论 / 125 阅读 / 正在检测是否收录...

简介

闲的无聊,写了一个基于 easyocr 图片转文字,用到了异步和websocket进行传输,图片是用base64编码后进行上传一次性识别图片文字并返回结果给请求端,在上传过程中图片不会保存到服务器上,这样也就避免了文件上传的安全性,同样在后端也做了一些安全限制,至于更安全些可以采用其它的方式比如验证等等。

redis

后端服务代码

import easyocr
import base64
import hashlib
import redis
import asyncio
import websockets
import json

max_size = 10 * 1024 * 1024

valid_formats = [
    'data:image/png;base64',
    'data:image/jpg;base64'
]

reader = easyocr.Reader(['ch_sim', 'en'], gpu=True)
cache = redis.StrictRedis(
    host='127.0.0.1',
    port=6379,
    password='@D208522',
)

async def ocr(websocket):
    async for message in websocket:
        try:
            if isinstance(message, str):
                message = json.loads(message)

            image_data = message.get('image')
            if not image_data or not any(image_data.startswith(fmt) for fmt in valid_formats):
                await websocket.send(json.dumps({'error': 'Invalid image format.'}))
                continue

            _, image_data = image_data.split(',', 1)
            image_bytes = base64.b64decode(image_data)

            if len(image_bytes) > max_size:
                await websocket.send(json.dumps({'error': 'Image too big.'}))
                continue

            cache_key = hashlib.md5(image_bytes).hexdigest()
            text = cache.get(cache_key)
            if text:
                await websocket.send(json.dumps({'status': 200, 'text': text.decode('utf-8')}))
                continue

            results = reader.readtext(image_bytes)
            text = '\n'.join([result[1] for result in results])
            cache.set(cache_key, text, ex=3600)
            await websocket.send(json.dumps({'status': 200, 'text': text}))

        except Exception as e:
            print(e)
            await websocket.send(json.dumps({'status': 500, 'text': 'Unknown error.'}))

async def start_server(host: str):
    async with websockets.serve(ocr, *host, max_size=max_size):
        await asyncio.Future()

if __name__ == '__main__':
    host = ("127.0.0.1", 5000)
    asyncio.run(start_server(host))

接口请求代码

import asyncio
import websockets
import base64
import json

async def send_image():
    async with websockets.connect('ws://127.0.0.1:5000/') as websocket:
        with open('E:\\Desktop\\1.png', 'rb') as f:
            image_data = f.read()

        image_base64 = base64.b64encode(image_data).decode('utf-8')
        message = {'image': 'data:image/png;base64,' + image_base64}
        await websocket.send(json.dumps(message))

        result = await websocket.recv()
        jsonText = json.loads(result)
        print(jsonText['text'])

if __name__ == '__main__':
    asyncio.run(send_image())

liimklbo.png

这里我截了一张文字图,用API的方式调用了下,返回的效果还是准确的,有些文字会识别不准确,但整体来说效果还是可以的。

liioogfa.png

前端代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>OCR Demo</title>
    <style>
        body {
            background-color: #f0f0f0;
        }

        .view {
            margin: 30px auto;
            max-width: 400px;
            padding: 50px;
            background-color: rgb(255, 255, 255);
            border-radius: 15px;
            box-shadow: 0px 3px 10px rgb(0 0 0 / 20%);
        }

        .container {
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 20px;
        }

        #imageInput {
            display: none;
        }

        label[for="imageInput"] {
            background-color: #007bff;
            color: white;
            padding: 10px;
            border-radius: 5px;
            cursor: pointer;
            box-shadow: 0px 3px 10px rgb(0 0 0 / 20%);
        }

        button {
            width: 60px;
            background-color: #007bff;
            color: white;
            padding: 10px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            box-shadow: 0px 3px 10px rgb(0 0 0 / 20%);
        }

        button:hover {
            background-color: #d90000;
        }

        #result {
            border-radius: 10px;
            font-size: 16px;
            text-align: center;
        }
    </style>
</head>

<body>
    <div class="view">
        <div class="container">
            <label for="imageInput">上传图片</label>
            <input type="file" id="imageInput" />
            <button onclick="submitImage()">提交</button>
        </div>

        <div id="result"></div>
    </div>
    <script>
        const websocket = new WebSocket('ws://127.0.0.1:5000');

        function submitImage() {
            const file = document.getElementById("imageInput").files[0];
            if (!file) return;

            const reader = new FileReader();
            reader.onload = function (event) {
                const image_data = event.target.result;
                websocket.send(JSON.stringify({ image: image_data }));
            };
            reader.readAsDataURL(file);
        }

        websocket.onmessage = function (event) {
            const response = JSON.parse(event.data);
            if ('text' in response) {
                document.getElementById('result').innerText = "识别结果:" + response.text;
            } else if ('error' in response) {
                document.getElementById('result').innerText = 'Error: ' + response.error;
            }
        };
    </script>
</body>
  
</html>

liiort5v.png

8

评论 (0)

取消
0:00