Tạo trang chuyển hình ảnh thành văn bản online cho blogspot

Anh Trai Nắng
07 tháng 9
Tips
Mục lục

Trong kỷ nguyên số, việc trích xuất văn bản từ hình ảnh ngày càng cần thiết – từ tài liệu scan, hóa đơn, đến ảnh chụp màn hình. Thay vì gõ lại thủ công, bạn có thể dùng OCR (Optical Character Recognition) để chuyển ảnh thành chữ chỉ trong vài giây.

Tạo trang chuyển hình ảnh thành văn bản online cho blogspot
Tạo trang chuyển hình ảnh thành văn bản online cho blogspot.

Trong bài viết này, mình sẽ hướng dẫn bạn cách tạo trang OCR online ngay trên Blogspot để người dùng có thể tải ảnh lên và nhận diện văn bản tức thì, hỗ trợ cả tiếng Việt và tiếng Anh.

🚀 Xem Demo

1. Giới thiệu OCR là gì?

Trong thời đại số, nhu cầu chuyển đổi thông tin từ hình ảnh sang văn bản ngày càng nhiều: scan tài liệu, chụp hoá đơn, lưu giữ thông tin từ ảnh chụp màn hình… Công nghệ OCR (Optical Character Recognition – Nhận dạng ký tự quang học) giúp chúng ta làm điều đó tự động.

OCR có thể đọc chữ trong hình ảnh, sau đó xuất ra văn bản để bạn dễ dàng copy, chỉnh sửa, hoặc lưu trữ. Điểm hay là hiện nay đã có thư viện chạy trực tiếp trên trình duyệt, không cần server – vừa tiện vừa an toàn.

2. Tại sao nên có trang OCR online riêng trên Blogspot?

  • Tiện ích cho độc giả: Người đọc blog của bạn có thể tải ảnh lên và lấy text ngay.
  • Không cần cài đặt: Chạy ngay trong trình duyệt, không cần phần mềm ngoài.
  • An toàn: Mọi xử lý diễn ra trên máy người dùng, không gửi ảnh đi đâu.
  • Hỗ trợ tiếng Việt: Nhờ dùng thư viện Tesseract.js.

3. Cách thêm trang OCR vào Blogspot

Vào Blogspot → Trang → Tạo trang mới.

Chuyển sang chế độ HTML.

Dán nguyên khối code sau (Mình đã chuẩn bị đầy đủ CSS + JS + Tesseract.js):

<section id="atn-ocr">
        <style>
        #atn-ocr {
            --bg: #f7fafc;
            --card: #fff;
            --text: #111827;
            --muted: #6b7280;
            --brand: #2563eb;
            --border: rgba(148, 163, 184, .35);
            --shadow: 0 6px 20px rgba(0, 0, 0, .08);
            --radius: 14px
        }

        @media(prefers-color-scheme:dark) {
            #atn-ocr {
                --bg: #0b1220;
                --card: #0f172a;
                --text: #e5e7eb;
                --muted: #9ca3af;
                --brand: #60a5fa;
                --border: rgba(148, 163, 184, .25);
                --shadow: 0 6px 20px rgba(0, 0, 0, .35)
            }
        }

        #atn-ocr {
            background: var(--bg);
            color: var(--text);
            font: 16px/1.6 system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial;
            padding: 32px 0
        }

        #atn-ocr .container {
            max-width: 760px;
            margin: 0 auto;
            padding: 0 16px
        }

        #atn-ocr header {
            text-align: center;
            margin-bottom: 24px
        }

        #atn-ocr h1 {
            margin: 0;
            font-size: clamp(26px, 4vw, 36px)
        }

        #atn-ocr .subtitle {
            color: var(--muted);
            font-size: 15px;
            margin-top: 6px
        }

        /* upload box */
        #atn-ocr .upload-box {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 10px;
            cursor: pointer;
            border: 2px dashed var(--border);
            border-radius: var(--radius);
            padding: 40px;
            background: var(--card);
            transition: .2s;
            text-align: center
        }

        #atn-ocr .upload-box:hover {
            border-color: var(--brand);
            background: #0b122006
        }

        #atn-ocr .upload-box svg {
            width: 48px;
            height: 48px;
            color: var(--brand)
        }

        #atn-ocr .preview {
            max-width: 100%;
            margin: 16px auto;
            display: none;
            border-radius: 10px;
            box-shadow: 0 3px 10px rgba(0, 0, 0, .15)
        }

        #atn-ocr progress {
            width: 100%;
            height: 10px;
            border-radius: 6px;
            overflow: hidden;
            margin-top: 12px
        }

        #atn-ocr .card {
            background: var(--card);
            border: 1px solid var(--border);
            border-radius: var(--radius);
            box-shadow: var(--shadow);
            padding: 20px;
            margin-top: 20px
        }

        #atn-ocr textarea {
            width: 100%;
            min-height: 220px;
            resize: vertical;
            border: 1px solid var(--border);
            border-radius: 10px;
            padding: 12px;
            font-family: ui-monospace, monospace;
            font-size: 15px;
            background: #0b122003;
            color: var(--text)
        }

        #atn-ocr .toolbar {
            display: flex;
            gap: 10px;
            margin-bottom: 10px;
            flex-wrap: wrap
        }

        #atn-ocr .btn {
            flex: 1;
            text-align: center;
            cursor: pointer;
            border: 1px solid var(--border);
            border-radius: 8px;
            background: linear-gradient(180deg, rgba(255, 255, 255, .08), rgba(0, 0, 0, .02));
            padding: 10px;
            font-size: 14px;
            color: var(--text);
            transition: .15s
        }

        #atn-ocr .btn:hover {
            border-color: var(--brand);
            background: #0b122006
        }

        #atn-ocr .toast {
            position: fixed;
            left: 50%;
            transform: translateX(-50%);
            bottom: 24px;
            background: var(--card);
            color: var(--text);
            border: 1px solid var(--border);
            box-shadow: var(--shadow);
            border-radius: 10px;
            padding: 10px 14px;
            font-size: 14px;
            display: none;
            z-index: 9999
        }
    </style>
        <div class="container">
                <header>
                        <h1>Chuyển hình ảnh thành văn bản (OCR online)</h1>
                        <p class="subtitle">Chọn hoặc kéo-thả ảnh vào khung bên dưới để nhận diện chữ (tiếng Việt + tiếng Anh).</p>
                    </header>
                <div class="card">
                        <div class="upload-box" id="dropzone">
                                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                                       
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a2 2 0 002 2h12a2 2 0 002-2v-1M12 12V4m0 0L8 8m4-4l4 4" />

                                   
                </svg>
                                <div><strong>Kéo & thả ảnh</strong> hoặc click để chọn</div>
                                <input type="file" id="file" accept="image/*" hidden>
                            </div>
                        <img id="preview" class="preview" alt="preview">
                        <progress id="progress" value="0" max="1" style="display:none"></progress>
                    </div>
                <div class="card">
                        <h2 style="margin-top:0;font-size:18px">Kết quả OCR</h2>
                        <div class="toolbar">
                                <button class="btn" id="btn-copy">📑 Copy</button>
                                <button class="btn" id="btn-clear">🧹 Xoá</button>
                                <button class="btn" id="btn-download">⬇️ Tải TXT</button>
                            </div>
                        <textarea id="output" placeholder="Văn bản sẽ hiện ở đây sau khi nhận diện…"></textarea>
                    </div>
            </div>
        <div id="toast" class="toast"></div>
        <!-- Tesseract.js -->
        <script src="https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js"></script>
        <script>
        (function() {
            const $ = s => document.querySelector(s);
            const file = $('#file'),
                dropzone = $('#dropzone'),
                preview = $('#preview'),
                progress = $('#progress'),
                output = $('#output'),
                toast = $('#toast');

            function showToast(msg) {
                toast.textContent = msg;
                toast.style.display = 'block';
                clearTimeout(showToast._t);
                showToast._t = setTimeout(() => toast.style.display = 'none', 1500);
            }

            function handleFile(f) {
                if (!f) return;
                preview.src = URL.createObjectURL(f);
                preview.style.display = 'block';
                output.value = '';
                progress.style.display = 'block';
                progress.value = 0;
                Tesseract.recognize(f, 'vie+eng', {
                    logger: m => {
                        if (m.status === 'recognizing text' && m.progress) progress.value = m.progress;
                    }
                }).then(({
                    data: {
                        text
                    }
                }) => {
                    output.value = text.trim();
                    progress.style.display = 'none';
                    showToast('Đã nhận diện xong ✅');
                }).catch(e => {
                    progress.style.display = 'none';
                    showToast('Lỗi OCR: ' + e.message);
                });
            }
            // click để chọn file
            dropzone.addEventListener('click', () => file.click());
            file.addEventListener('change', e => handleFile(e.target.files[0]));
            // drag-drop
            ['dragenter', 'dragover'].forEach(ev =>
                dropzone.addEventListener(ev, e => {
                    e.preventDefault();
                    dropzone.classList.add('dragover');
                }));
            ['dragleave', 'drop'].forEach(ev =>
                dropzone.addEventListener(ev, e => {
                    e.preventDefault();
                    dropzone.classList.remove('dragover');
                }));
            dropzone.addEventListener('drop', e => handleFile(e.dataTransfer.files[0]));
            // toolbar
            $('#btn-copy').addEventListener('click', async () => {
                if (!output.value) {
                    showToast('Chưa có văn bản');
                    return;
                }
                try {
                    await navigator.clipboard.writeText(output.value);
                    showToast('Đã copy văn bản');
                } catch {
                    showToast('Copy không thành công');
                }
            });
            $('#btn-clear').addEventListener('click', () => {
                output.value = '';
                preview.src = '';
                preview.style.display = 'none';
                file.value = '';
            });
            $('#btn-download').addEventListener('click', () => {
                if (!output.value) {
                    showToast('Chưa có văn bản');
                    return;
                }
                const blob = new Blob([output.value], {
                    type: 'text/plain'
                });
                const a = document.createElement('a');
                a.href = URL.createObjectURL(blob);
                a.download = 'ocr-result.txt';
                a.click();
            });
        })();
    </script>
</section>

👉 Code này sẽ tạo ra một giao diện đẹp, có:

  • Khung upload ảnh (kéo-thả hoặc click chọn).
  • Xem trước ảnh vừa tải lên.
  • Thanh progress nhận diện chữ.
  • Khung kết quả văn bản với các nút Copy / Xoá / Tải TXT.
  • Hỗ trợ tiếng Việt + tiếng Anh.
  • Dark mode tự động theo máy người dùng.

4. Kết luận

Vậy là chỉ với vài bước đơn giản, anh đã có thể biến blogspot thành nơi độc giả dễ dàng chuyển hình ảnh thành văn bản trực tuyến. Đây là một tiện ích cực kỳ hữu ích, đặc biệt cho những ai hay làm việc với tài liệu scan, ảnh chụp, hoặc muốn tiết kiệm thời gian gõ lại văn bản thủ công.

Hãy thử áp dụng ngay cho blog của mình nhé! 🚀

Chia sẻ:
Đã sao chép link!

Bài viết liên quan

Nhận xét (14)

Hiển thị
  1. Hay đấy nhỉ? Thêm cái ảnh bên cạnh để đối chiếu nữa thì ok đấy

    Trả lờiXóa
    Trả lời
    1. Ở chỗ bình luận mới nhất thấy bác đang highlight theo tên "Anh Trai Nắng" không được tối ưu lắm, thằng nào nó cũng đặt tên thế thì cũng highlight luôn, bác nên để theo ID không ai fake được 😁

      Xóa
    2. chắc ko đến nổi nó đặt tên giống vậy đâu 😁

      Xóa
    3. Favicon ở chỗ "Blog bạn bè" đang bị lỗi ở những link ngoài blogspot kìa. Tìm đoạn code hiển thị favicon rồi thay bằng đoạn dưới xem sao bác
      <img alt='favicon' expr:src='&quot;https://t0.gstatic.com/faviconV2?client=SOCIAL&amp;type=FAVICON&amp;fallback_opts=TYPE,SIZE,URL&amp;size=32&amp;url=&quot; + data:item.blogUrl'/>

      Xóa
    4. này thay vào lỗi toàn bộ icon luôn, đang tính rãnh làm cái Danh sách blog giống ông.

      Xóa
    5. Vậy tóm lại làm sao để link hình ảnh nó dạng này là được https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&size=32&url=https://www.anhtrainang.com/ 😁

      Xóa
    6. thay cái ông gửi vào ổn áp rồi nha, thanks 👍

      Xóa
  2. Thêm nút "Copy all" nội dung nữa sẽ tiện lợi nè.

    Trả lờiXóa
  3. Tool này nên thêm tí chức năng văn bản (vd tự động viết hoa, xóa dấu,...) sau khi chuyển từ hình ảnh sang văn bản là ngon luôn.

    Trả lờiXóa

Đăng nhận xét