{"id":612,"date":"2026-08-13T11:02:29","date_gmt":"2026-08-13T04:02:29","guid":{"rendered":"https:\/\/app.mitunet.com\/home\/?page_id=612"},"modified":"2026-08-15T18:21:18","modified_gmt":"2026-08-15T11:21:18","slug":"lam-mo-nen-anh","status":"publish","type":"page","link":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/","title":{"rendered":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3"},"content":{"rendered":"<div id=\"tdi_1\" class=\"tdc-zone\"><div class=\"tdc_zone tdi_2  wpb_row td-pb-row\"  >\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_2{\r\n                    min-height: 0;\r\n                }\n<\/style><div id=\"tdi_3\" class=\"tdc-row stretch_row_1400 td-stretch-content\"><div class=\"vc_row tdi_4  wpb_row td-pb-row\" >\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_4,\r\n                .tdi_4 .tdc-columns{\r\n                    min-height: 0;\r\n                }.tdi_4,\r\n\t\t\t\t.tdi_4 .tdc-columns{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_4 .tdc-columns{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}.tdi_4:before,\r\n\t\t\t\t.tdi_4:after{\r\n\t\t\t\t    display: table;\r\n\t\t\t\t}\n<\/style><div class=\"vc_column tdi_6  wpb_column vc_column_container tdc-column td-pb-span12\">\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_6{\r\n                    vertical-align: baseline;\r\n                }.tdi_6 > .wpb_wrapper,\r\n\t\t\t\t.tdi_6 > .wpb_wrapper > .tdc-elements{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_6 > .wpb_wrapper > .tdc-elements{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}.tdi_6 > .wpb_wrapper > .vc_row_inner{\r\n\t\t\t\t    width: auto;\r\n\t\t\t\t}.tdi_6 > .wpb_wrapper{\r\n\t\t\t\t    width: auto;\r\n\t\t\t\t    height: auto;\r\n\t\t\t\t}\n<\/style><div class=\"wpb_wrapper\" ><div class=\"vc_row_inner tdi_8  vc_row vc_inner wpb_row td-pb-row\" >\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_8{\r\n                    position: relative !important;\r\n                    top: 0;\r\n                    transform: none;\r\n                    -webkit-transform: none;\r\n                }.tdi_8,\r\n\t\t\t\t.tdi_8 .tdc-inner-columns{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_8 .tdc-inner-columns{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}\n<\/style><div class=\"vc_column_inner tdi_10  wpb_column vc_column_container tdc-inner-column td-pb-span12\">\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_10{\r\n                    vertical-align: baseline;\r\n                }.tdi_10 .vc_column-inner > .wpb_wrapper,\r\n\t\t\t\t.tdi_10 .vc_column-inner > .wpb_wrapper .tdc-elements{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_10 .vc_column-inner > .wpb_wrapper .tdc-elements{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}\n<\/style><div class=\"vc_column-inner\"><div class=\"wpb_wrapper\" ><div class=\"wpb_wrapper wpb_text_column td_block_wrap td_block_wrap vc_column_text tdi_11  tagdiv-type td-pb-border-top td_block_template_1\"  data-td-block-uid=\"tdi_11\" >\n<style>\n\n\/* inline tdc_css att - generated by TagDiv Composer *\/\n\n.tdi_11{\npadding-top:20px !important;\npadding-bottom:5px !important;\n--tdb-scroll-anim:none !important;\nposition:relative;\n}\n\n<\/style>\n<style>\n\/* custom css - generated by TagDiv Composer *\/\n.vc_column_text > .td-element-style{\r\n\t\t\t\t\tz-index: -1;\r\n\t\t\t\t}\n<\/style>\n<div class=\"tdi_11_rand_style td-element-style\"><style>\n.tdi_11_rand_style{\nbackground-color:#cee8be !important;\n}\n <\/style><\/div><div class=\"td-fix-index\"><h1>C\u00f4ng C\u1ee5 L\u00e0m M\u1edd N\u1ec1n \u1ea2nh Online Chuy\u00ean Nghi\u1ec7p, L\u00e0m M\u1edd N\u1ec1n H\u00ecnh \u1ea2nh B\u1eb1ng AI<\/h1>\n<\/div><\/div><div class=\"wpb_wrapper wpb_text_column td_block_wrap td_block_wrap vc_column_text tdi_12  tagdiv-type td-pb-border-top td_block_template_1\"  data-td-block-uid=\"tdi_12\" ><div class=\"td-fix-index\">\n    <div id=\"aib31-app\">\n\n        <!-- =====================================================\n             HEADER\n        ====================================================== -->\n\n        <div class=\"aib31-header\">\n\n            <div class=\"aib31-title-box\">\n\n                <h2>\n                    C\u00f4ng C\u1ee5 AI L\u00e0m M\u1edd N\u1ec1n \u1ea2nh Online Mi\u1ec5n Ph\u00ed T\u1ed1t Nh\u1ea5t\n                <\/h2>\n\n                <p>\n                    Nh\u1eadn di\u1ec7n ch\u1ee7 th\u1ec3 b\u1eb1ng AI v\u00e0 l\u00e0m m\u1edd ph\u1ea7n n\u1ec1n nhanh ch\u00f3ng ngay tr\u00ean tr\u00ecnh duy\u1ec7t.\n                <\/p>\n\n            <\/div>\n\n            <div class=\"aib31-status\" id=\"aib31-status\">\n                Ch\u01b0a t\u1ea3i \u1ea3nh\n            <\/div>\n\n        <\/div>\n\n\n        <!-- =====================================================\n             MAIN LAYOUT\n        ====================================================== -->\n\n        <div class=\"aib31-layout\">\n\n\n            <!-- =================================================\n                 LEFT - IMAGE\n            ================================================== -->\n\n            <div class=\"aib31-preview-column\">\n\n                <div class=\"aib31-preview-sticky\">\n\n                    <div class=\"aib31-preview-title\">\n\n                        <span>\n                            \u1ea2nh xem tr\u01b0\u1edbc\n                        <\/span>\n\n                        <span id=\"aib31-dimensions\"><\/span>\n\n                    <\/div>\n\n\n                    <div class=\"aib31-canvas-wrap\">\n\n                        <canvas id=\"aib31-canvas\"><\/canvas>\n\n\n                        <div id=\"aib31-empty\">\n\n                            <div class=\"aib31-upload-icon\">\n                                \ud83d\uddbc\ufe0f\n                            <\/div>\n\n                            <strong>\n                                Ch\u01b0a c\u00f3 \u1ea3nh\n                            <\/strong>\n\n                            <span>\n                                H\u00e3y ch\u1ecdn m\u1ed9t \u1ea3nh \u0111\u1ec3 b\u1eaft \u0111\u1ea7u\n                            <\/span>\n\n                        <\/div>\n\n                    <\/div>\n\n\n                    <div\n                        class=\"aib31-preview-mode\"\n                        id=\"aib31-preview-mode\"\n                    >\n                        \u1ea2nh g\u1ed1c\n                    <\/div>\n\n                <\/div>\n\n            <\/div>\n\n\n            <!-- =================================================\n                 RIGHT - TOOLS\n            ================================================== -->\n\n            <div class=\"aib31-tools-column\">\n\n\n                <!-- =================================================\n                     UPLOAD\n                ================================================== -->\n\n                <section class=\"aib31-card\">\n\n                    <h3>\n                        1. Ch\u1ecdn \u1ea3nh\n                    <\/h3>\n\n                    <label class=\"aib31-upload-btn\">\n\n                        <input\n                            type=\"file\"\n                            id=\"aib31-file\"\n                            accept=\"image\/jpeg,image\/png,image\/webp\"\n                        >\n\n                        <span>\n                            \ud83d\udcc1 Ch\u1ecdn \u1ea3nh\n                        <\/span>\n\n                    <\/label>\n\n                    <div class=\"aib31-small-note\">\n                        JPG, PNG ho\u1eb7c WEBP\n                    <\/div>\n\n                <\/section>\n\n\n                <!-- =================================================\n                     AI\n                ================================================== -->\n\n                <section class=\"aib31-card\">\n\n                    <h3>\n                        2. AI nh\u1eadn di\u1ec7n ch\u1ee7 th\u1ec3\n                    <\/h3>\n\n                    <p class=\"aib31-description\">\n                        AI s\u1ebd ph\u00e2n t\u00edch \u1ea3nh v\u00e0 t\u1ea1o v\u00f9ng mask.\n                        B\u1ea1n c\u00f3 th\u1ec3 xem tr\u01b0\u1edbc mask tr\u01b0\u1edbc khi l\u00e0m m\u1edd n\u1ec1n.\n                    <\/p>\n\n                    <button\n                        type=\"button\"\n                        id=\"aib31-ai-btn\"\n                        class=\"aib31-primary\"\n                        disabled\n                    >\n                        \ud83e\udd16 Nh\u1eadn di\u1ec7n b\u1eb1ng AI\n                    <\/button>\n\n\n                    <div\n                        id=\"aib31-ai-progress\"\n                        class=\"aib31-progress-box\"\n                    >\n\n                        <div class=\"aib31-spinner\"><\/div>\n\n                        <span id=\"aib31-progress-text\">\n                            \u0110ang chu\u1ea9n b\u1ecb AI...\n                        <\/span>\n\n                    <\/div>\n\n                <\/section>\n\n\n                <!-- =================================================\n                     OBJECTS\n                ================================================== -->\n\n                <section\n                    class=\"aib31-card\"\n                    id=\"aib31-objects-card\"\n                    style=\"display:none;\"\n                >\n\n                    <h3>\n                        3. Ch\u1ecdn ch\u1ee7 th\u1ec3\n                    <\/h3>\n\n                    <p class=\"aib31-description\">\n                        Ch\u1ecdn v\u00f9ng ch\u1ee7 th\u1ec3 m\u00e0 b\u1ea1n mu\u1ed1n gi\u1eef r\u00f5.\n                    <\/p>\n\n                    <div id=\"aib31-objects\"><\/div>\n\n                    <button\n                        type=\"button\"\n                        id=\"aib31-mask-btn\"\n                        class=\"aib31-secondary\"\n                    >\n                        \ud83d\udc41\ufe0f Xem tr\u01b0\u1edbc Mask\n                    <\/button>\n\n                <\/section>\n\n\n                <!-- =================================================\n                     MASK\n                ================================================== -->\n\n                <section\n                    class=\"aib31-card\"\n                    id=\"aib31-mask-card\"\n                    style=\"display:none;\"\n                >\n\n                    <h3>\n                        4. Ki\u1ec3m tra Mask AI\n                    <\/h3>\n\n\n                    <div class=\"aib31-mask-preview\">\n\n                        <canvas\n                            id=\"aib31-mask-canvas\"\n                        ><\/canvas>\n\n                    <\/div>\n\n\n                    <div class=\"aib31-control\">\n\n                        <label>\n\n                            <span>\n                                \u0110\u1ed9 nh\u1ea1y mask\n                            <\/span>\n\n                            <strong id=\"aib31-threshold-value\">\n                                50%\n                            <\/strong>\n\n                        <\/label>\n\n                        <input\n                            type=\"range\"\n                            id=\"aib31-threshold\"\n                            min=\"10\"\n                            max=\"90\"\n                            value=\"50\"\n                        >\n\n                    <\/div>\n\n\n                    <p class=\"aib31-mask-note\">\n\n                        V\u00f9ng s\u00e1ng l\u00e0 ch\u1ee7 th\u1ec3 \u0111\u01b0\u1ee3c gi\u1eef r\u00f5.\n                        V\u00f9ng t\u1ed1i s\u1ebd b\u1ecb l\u00e0m m\u1edd.\n\n                    <\/p>\n\n                <\/section>\n\n\n                <!-- =================================================\n                     BLUR\n                ================================================== -->\n\n                <section class=\"aib31-card\">\n\n                    <h3>\n                        5. L\u00e0m m\u1edd\n                    <\/h3>\n\n\n                    <div class=\"aib31-control\">\n\n                        <label>\n\n                            <span>\n                                \u0110\u1ed9 m\u1edd\n                            <\/span>\n\n                            <strong id=\"aib31-blur-value\">\n                                18px\n                            <\/strong>\n\n                        <\/label>\n\n                        <input\n                            type=\"range\"\n                            id=\"aib31-blur\"\n                            min=\"2\"\n                            max=\"50\"\n                            value=\"18\"\n                        >\n\n                    <\/div>\n\n\n                    <button\n                        type=\"button\"\n                        id=\"aib31-background-btn\"\n                        class=\"aib31-primary\"\n                        disabled\n                    >\n                        \ud83c\udf2b\ufe0f L\u00e0m m\u1edd n\u1ec1n\n                    <\/button>\n\n\n                    <button\n                        type=\"button\"\n                        id=\"aib31-full-btn\"\n                        class=\"aib31-secondary\"\n                        disabled\n                    >\n                        \ud83d\udd32 L\u00e0m m\u1edd to\u00e0n \u1ea3nh\n                    <\/button>\n\n                <\/section>\n\n\n                <!-- =================================================\n                     HISTORY\n                ================================================== -->\n\n                <section class=\"aib31-card\">\n\n                    <h3>\n                        6. Ch\u1ec9nh s\u1eeda\n                    <\/h3>\n\n\n                    <div class=\"aib31-two-buttons\">\n\n                        <button\n                            type=\"button\"\n                            id=\"aib31-undo\"\n                            disabled\n                        >\n                            \u21a9 Ho\u00e0n t\u00e1c\n                        <\/button>\n\n                        <button\n                            type=\"button\"\n                            id=\"aib31-redo\"\n                            disabled\n                        >\n                            \u21aa L\u00e0m l\u1ea1i\n                        <\/button>\n\n                    <\/div>\n\n\n                    <button\n                        type=\"button\"\n                        id=\"aib31-original\"\n                        disabled\n                    >\n                        \ud83d\udd04 Hi\u1ec7n \u1ea3nh g\u1ed1c\n                    <\/button>\n\n\n                    <button\n                        type=\"button\"\n                        id=\"aib31-reset\"\n                        disabled\n                    >\n                        \u267b\ufe0f L\u00e0m l\u1ea1i t\u1eeb \u0111\u1ea7u\n                    <\/button>\n\n                <\/section>\n\n\n                <!-- =================================================\n                     EXPORT\n                ================================================== -->\n\n                <section class=\"aib31-card\">\n\n                    <h3>\n                        7. L\u01b0u \u1ea3nh\n                    <\/h3>\n\n\n                    <select id=\"aib31-format\">\n\n                        <option value=\"image\/png\">\n                            PNG\n                        <\/option>\n\n                        <option value=\"image\/jpeg\">\n                            JPG\n                        <\/option>\n\n                        <option value=\"image\/webp\">\n                            WEBP\n                        <\/option>\n\n                    <\/select>\n\n\n                    <button\n                        type=\"button\"\n                        id=\"aib31-download\"\n                        class=\"aib31-download\"\n                        disabled\n                    >\n                        \u2b07\ufe0f T\u1ea3i \u1ea3nh xu\u1ed1ng\n                    <\/button>\n\n                <\/section>\n\n            <\/div>\n\n        <\/div>\n\n    <\/div>\n\n\n<style>\n\n\/* =========================================================\n   ROOT\n========================================================= *\/\n\n#aib31-app {\n\n    --aib31-border: #e5e7eb;\n    --aib31-text: #111827;\n    --aib31-muted: #6b7280;\n    --aib31-bg: #f5f7fa;\n\n    width: 100%;\n    max-width: 1450px;\n\n    margin: 20px auto;\n\n    box-sizing: border-box;\n\n    font-family:\n        Inter,\n        -apple-system,\n        BlinkMacSystemFont,\n        \"Segoe UI\",\n        Arial,\n        sans-serif;\n\n    color: var(--aib31-text);\n}\n\n#aib31-app * {\n    box-sizing: border-box;\n}\n\n\n\/* =========================================================\n   HEADER\n========================================================= *\/\n\n.aib31-header {\n\n    display: flex;\n\n    justify-content: space-between;\n\n    align-items: center;\n\n    gap: 20px;\n\n    margin-bottom: 20px;\n}\n\n\n\/* =========================================================\n   TITLE BOX\n========================================================= *\/\n\n.aib31-title-box {\n\n    flex: 1;\n\n    background:\n        linear-gradient(\n            135deg,\n            #f8fafc,\n            #eef2ff\n        );\n\n    border: 1px solid #dbe3f0;\n\n    border-radius: 14px;\n\n    padding: 18px 22px;\n\n    box-shadow:\n        0 3px 12px rgba(\n            0,\n            0,\n            0,\n            0.05\n        );\n}\n\n\n.aib31-title-box h2 {\n\n    margin: 0 0 6px;\n\n    font-size: 25px;\n\n    font-weight: 700;\n\n    line-height: 1.3;\n\n    color: #111827;\n}\n\n\n.aib31-title-box p {\n\n    margin: 0;\n\n    color: #64748b;\n\n    font-size: 14px;\n\n    line-height: 1.5;\n}\n\n\n\/* =========================================================\n   STATUS\n========================================================= *\/\n\n.aib31-status {\n\n    flex-shrink: 0;\n\n    padding: 9px 14px;\n\n    background: #f3f4f6;\n\n    border-radius: 999px;\n\n    font-size: 13px;\n}\n\n\n\/* =========================================================\n   MAIN LAYOUT\n========================================================= *\/\n\n.aib31-layout {\n\n    display: grid;\n\n    grid-template-columns:\n        minmax(0, 1fr)\n        390px;\n\n    gap: 22px;\n\n    align-items: start;\n}\n\n\n\/* =========================================================\n   PREVIEW\n========================================================= *\/\n\n.aib31-preview-column {\n\n    min-width: 0;\n}\n\n\n.aib31-preview-sticky {\n\n    position: sticky;\n\n    top: 20px;\n}\n\n\n.aib31-preview-title {\n\n    display: flex;\n\n    justify-content: space-between;\n\n    margin-bottom: 10px;\n\n    font-weight: 700;\n}\n\n\n.aib31-canvas-wrap {\n\n    position: relative;\n\n    width: 100%;\n\n    min-height: 500px;\n\n    background:\n        repeating-conic-gradient(\n            #f1f1f1 0% 25%,\n            #ffffff 0% 50%\n        )\n        50% \/ 24px 24px;\n\n    border: 1px solid var(--aib31-border);\n\n    border-radius: 14px;\n\n    display: flex;\n\n    align-items: center;\n\n    justify-content: center;\n\n    overflow: hidden;\n}\n\n\n#aib31-canvas {\n\n    display: none;\n\n    max-width: 100%;\n\n    max-height: 78vh;\n\n    width: auto;\n\n    height: auto;\n}\n\n\n#aib31-empty {\n\n    display: flex;\n\n    flex-direction: column;\n\n    align-items: center;\n\n    gap: 8px;\n\n    color: #6b7280;\n}\n\n\n.aib31-upload-icon {\n\n    font-size: 45px;\n}\n\n\n.aib31-preview-mode {\n\n    text-align: center;\n\n    color: #6b7280;\n\n    font-size: 13px;\n\n    padding-top: 9px;\n}\n\n\n\/* =========================================================\n   TOOLS\n========================================================= *\/\n\n.aib31-tools-column {\n\n    max-height:\n        calc(100vh - 40px);\n\n    overflow-y: auto;\n\n    padding-right: 5px;\n\n    scrollbar-width: thin;\n}\n\n\n\/* =========================================================\n   CARD\n========================================================= *\/\n\n.aib31-card {\n\n    background: #ffffff;\n\n    border: 1px solid var(--aib31-border);\n\n    border-radius: 13px;\n\n    padding: 17px;\n\n    margin-bottom: 15px;\n\n    box-shadow:\n        0 2px 8px rgba(\n            0,\n            0,\n            0,\n            0.035\n        );\n}\n\n\n.aib31-card h3 {\n\n    margin: 0 0 12px;\n\n    font-size: 16px;\n}\n\n\n\/* =========================================================\n   TEXT\n========================================================= *\/\n\n.aib31-description,\n.aib31-small-note {\n\n    color: var(--aib31-muted);\n\n    font-size: 13px;\n\n    line-height: 1.5;\n}\n\n\n.aib31-small-note {\n\n    margin-top: 8px;\n}\n\n\n\/* =========================================================\n   BUTTONS\n========================================================= *\/\n\n.aib31-upload-btn,\n.aib31-primary,\n.aib31-secondary,\n.aib31-download,\n.aib31-card button,\n#aib31-format {\n\n    width: 100%;\n\n    min-height: 44px;\n\n    border-radius: 9px;\n\n    border: 1px solid var(--aib31-border);\n\n    font-size: 14px;\n\n    font-weight: 600;\n\n    cursor: pointer;\n}\n\n\n.aib31-upload-btn {\n\n    display: flex;\n\n    justify-content: center;\n\n    align-items: center;\n\n    background: #111827;\n\n    color: #ffffff;\n}\n\n\n.aib31-upload-btn input {\n\n    display: none;\n}\n\n\n.aib31-primary {\n\n    background: #111827;\n\n    color: #ffffff;\n\n    border-color: #111827;\n}\n\n\n.aib31-secondary {\n\n    background: #ffffff;\n\n    color: #111827;\n}\n\n\n.aib31-download {\n\n    background: #16a34a;\n\n    color: #ffffff;\n\n    border-color: #16a34a;\n\n    margin-top: 10px;\n}\n\n\n.aib31-card button {\n\n    margin-top: 9px;\n\n    background: #ffffff;\n\n    color: #111827;\n}\n\n\n.aib31-card button:disabled {\n\n    opacity: .45;\n\n    cursor: not-allowed;\n}\n\n\n\/* =========================================================\n   RANGE\n========================================================= *\/\n\n.aib31-control {\n\n    margin: 15px 0;\n}\n\n\n.aib31-control label {\n\n    display: flex;\n\n    justify-content: space-between;\n\n    font-size: 13px;\n\n    margin-bottom: 8px;\n}\n\n\n.aib31-control input[type=\"range\"] {\n\n    width: 100%;\n}\n\n\n\/* =========================================================\n   AI PROGRESS\n========================================================= *\/\n\n.aib31-progress-box {\n\n    display: none;\n\n    align-items: center;\n\n    gap: 10px;\n\n    margin-top: 12px;\n\n    padding: 11px;\n\n    border-radius: 8px;\n\n    background: #f3f4f6;\n\n    font-size: 13px;\n}\n\n\n.aib31-spinner {\n\n    width: 17px;\n\n    height: 17px;\n\n    border: 2px solid #d1d5db;\n\n    border-top-color: #111827;\n\n    border-radius: 50%;\n\n    animation:\n        aib31-spin\n        .8s linear infinite;\n}\n\n\n@keyframes aib31-spin {\n\n    to {\n        transform: rotate(360deg);\n    }\n\n}\n\n\n\/* =========================================================\n   OBJECTS\n========================================================= *\/\n\n.aib31-object {\n\n    display: flex;\n\n    align-items: center;\n\n    gap: 9px;\n\n    padding: 10px;\n\n    border: 1px solid var(--aib31-border);\n\n    border-radius: 8px;\n\n    margin-bottom: 7px;\n\n    cursor: pointer;\n}\n\n\n.aib31-object input {\n\n    width: 17px;\n\n    height: 17px;\n}\n\n\n.aib31-object-info {\n\n    flex: 1;\n}\n\n\n.aib31-object-name {\n\n    font-weight: 600;\n\n    font-size: 14px;\n}\n\n\n.aib31-object-score {\n\n    color: #6b7280;\n\n    font-size: 12px;\n}\n\n\n\/* =========================================================\n   MASK\n========================================================= *\/\n\n.aib31-mask-preview {\n\n    background:\n        repeating-conic-gradient(\n            #ddd 0% 25%,\n            #fff 0% 50%\n        )\n        50% \/ 18px 18px;\n\n    border-radius: 9px;\n\n    overflow: hidden;\n\n    border: 1px solid var(--aib31-border);\n}\n\n\n#aib31-mask-canvas {\n\n    display: block;\n\n    width: 100%;\n\n    height: auto;\n}\n\n\n.aib31-mask-note {\n\n    color: #6b7280;\n\n    font-size: 12px;\n\n    line-height: 1.5;\n}\n\n\n\/* =========================================================\n   SELECT\n========================================================= *\/\n\n#aib31-format {\n\n    background: #ffffff;\n\n    color: #111827;\n\n    padding: 0 12px;\n\n    appearance: auto;\n}\n\n\n\/* =========================================================\n   HISTORY\n========================================================= *\/\n\n.aib31-two-buttons {\n\n    display: grid;\n\n    grid-template-columns:\n        1fr 1fr;\n\n    gap: 8px;\n}\n\n\n\/* =========================================================\n   MOBILE\n========================================================= *\/\n\n@media (max-width: 900px) {\n\n    .aib31-header {\n\n        flex-direction: column;\n\n        align-items: stretch;\n    }\n\n\n    .aib31-status {\n\n        width: fit-content;\n    }\n\n\n    .aib31-layout {\n\n        grid-template-columns: 1fr;\n    }\n\n\n    .aib31-preview-sticky {\n\n        position: relative;\n\n        top: auto;\n    }\n\n\n    .aib31-tools-column {\n\n        max-height: none;\n\n        overflow: visible;\n    }\n\n\n    .aib31-canvas-wrap {\n\n        min-height: 300px;\n    }\n\n\n    .aib31-title-box h2 {\n\n        font-size: 21px;\n    }\n\n}\n\n\n@media (max-width: 500px) {\n\n    .aib31-title-box {\n\n        padding: 15px 16px;\n    }\n\n\n    .aib31-title-box h2 {\n\n        font-size: 19px;\n    }\n\n\n    .aib31-title-box p {\n\n        font-size: 13px;\n    }\n\n}\n\n<\/style>\n\n\n<script type=\"module\">\n\n(async function () {\n\n\"use strict\";\n\n\n\/* =========================================================\n   CONFIG\n========================================================= *\/\n\nconst MODEL =\n    \"Xenova\/segformer-b0-finetuned-ade-512-512\";\n\nconst LIBRARY =\n    \"https:\/\/cdn.jsdelivr.net\/npm\/@huggingface\/transformers@3.8.1\";\n\n\n\/* =========================================================\n   ELEMENTS\n========================================================= *\/\n\nconst app =\n    document.getElementById(\n        \"aib31-app\"\n    );\n\nif (!app) {\n    return;\n}\n\n\nconst fileInput =\n    document.getElementById(\n        \"aib31-file\"\n    );\n\n\nconst canvas =\n    document.getElementById(\n        \"aib31-canvas\"\n    );\n\n\nconst ctx =\n    canvas.getContext(\n        \"2d\",\n        {\n            willReadFrequently: true\n        }\n    );\n\n\nconst maskCanvas =\n    document.getElementById(\n        \"aib31-mask-canvas\"\n    );\n\n\nconst maskCtx =\n    maskCanvas.getContext(\n        \"2d\",\n        {\n            willReadFrequently: true\n        }\n    );\n\n\nconst empty =\n    document.getElementById(\n        \"aib31-empty\"\n    );\n\n\nconst status =\n    document.getElementById(\n        \"aib31-status\"\n    );\n\n\nconst dimensions =\n    document.getElementById(\n        \"aib31-dimensions\"\n    );\n\n\nconst mode =\n    document.getElementById(\n        \"aib31-preview-mode\"\n    );\n\n\nconst aiBtn =\n    document.getElementById(\n        \"aib31-ai-btn\"\n    );\n\n\nconst aiProgress =\n    document.getElementById(\n        \"aib31-ai-progress\"\n    );\n\n\nconst progressText =\n    document.getElementById(\n        \"aib31-progress-text\"\n    );\n\n\nconst objectsBox =\n    document.getElementById(\n        \"aib31-objects\"\n    );\n\n\nconst objectsCard =\n    document.getElementById(\n        \"aib31-objects-card\"\n    );\n\n\nconst maskBtn =\n    document.getElementById(\n        \"aib31-mask-btn\"\n    );\n\n\nconst maskCard =\n    document.getElementById(\n        \"aib31-mask-card\"\n    );\n\n\nconst threshold =\n    document.getElementById(\n        \"aib31-threshold\"\n    );\n\n\nconst thresholdValue =\n    document.getElementById(\n        \"aib31-threshold-value\"\n    );\n\n\nconst blurRange =\n    document.getElementById(\n        \"aib31-blur\"\n    );\n\n\nconst blurValue =\n    document.getElementById(\n        \"aib31-blur-value\"\n    );\n\n\nconst backgroundBtn =\n    document.getElementById(\n        \"aib31-background-btn\"\n    );\n\n\nconst fullBtn =\n    document.getElementById(\n        \"aib31-full-btn\"\n    );\n\n\nconst undoBtn =\n    document.getElementById(\n        \"aib31-undo\"\n    );\n\n\nconst redoBtn =\n    document.getElementById(\n        \"aib31-redo\"\n    );\n\n\nconst originalBtn =\n    document.getElementById(\n        \"aib31-original\"\n    );\n\n\nconst resetBtn =\n    document.getElementById(\n        \"aib31-reset\"\n    );\n\n\nconst downloadBtn =\n    document.getElementById(\n        \"aib31-download\"\n    );\n\n\nconst format =\n    document.getElementById(\n        \"aib31-format\"\n    );\n\n\n\/* =========================================================\n   STATE\n========================================================= *\/\n\nlet image =\n    new Image();\n\nlet imageLoaded =\n    false;\n\nlet sourceDataURL =\n    \"\";\n\nlet originalImageData =\n    null;\n\nlet currentImageData =\n    null;\n\nlet aiResults =\n    [];\n\nlet selectedResults =\n    [];\n\nlet generatedMask =\n    null;\n\nlet aiReady =\n    false;\n\nlet segmentationPipeline =\n    null;\n\nlet history =\n    [];\n\nlet historyIndex =\n    -1;\n\n\n\/* =========================================================\n   LOAD TRANSFORMERS\n========================================================= *\/\n\nlet pipeline;\n\n\nasync function loadLibrary() {\n\n    setStatus(\n        \"\u0110ang t\u1ea3i th\u01b0 vi\u1ec7n AI...\",\n        \"loading\"\n    );\n\n\n    try {\n\n        const mod =\n            await import(\n                LIBRARY\n            );\n\n\n        pipeline =\n            mod.pipeline;\n\n\n        if (!pipeline) {\n\n            throw new Error(\n                \"Kh\u00f4ng t\u00ecm th\u1ea5y pipeline.\"\n            );\n\n        }\n\n\n        return true;\n\n\n    } catch (error) {\n\n        console.error(\n            error\n        );\n\n\n        setStatus(\n            \"Kh\u00f4ng th\u1ec3 t\u1ea3i th\u01b0 vi\u1ec7n AI\",\n            \"error\"\n        );\n\n\n        return false;\n\n    }\n\n}\n\n\n\/* =========================================================\n   LOAD MODEL\n========================================================= *\/\n\nasync function loadModel() {\n\n    if (aiReady) {\n        return true;\n    }\n\n\n    aiProgress.style.display =\n        \"flex\";\n\n\n    progressText.textContent =\n        \"\u0110ang t\u1ea3i model AI l\u1ea7n \u0111\u1ea7u...\";\n\n\n    try {\n\n        let options = {};\n\n\n        if (\n            typeof navigator !==\n            \"undefined\" &&\n            navigator.gpu\n        ) {\n\n            options = {\n\n                device:\n                    \"webgpu\",\n\n                dtype:\n                    \"fp16\"\n\n            };\n\n        } else {\n\n            options = {\n\n                device:\n                    \"wasm\",\n\n                dtype:\n                    \"q8\"\n\n            };\n\n        }\n\n\n        segmentationPipeline =\n            await pipeline(\n                \"image-segmentation\",\n                MODEL,\n                options\n            );\n\n\n        aiReady =\n            true;\n\n\n        aiProgress.style.display =\n            \"none\";\n\n\n        setStatus(\n            \"AI \u0111\u00e3 s\u1eb5n s\u00e0ng\",\n            \"success\"\n        );\n\n\n        return true;\n\n\n    } catch (error) {\n\n        console.error(\n            \"AI MODEL ERROR:\",\n            error\n        );\n\n\n        if (\n            typeof navigator !==\n            \"undefined\" &&\n            navigator.gpu\n        ) {\n\n            try {\n\n                progressText.textContent =\n                    \"\u0110ang chuy\u1ec3n sang ch\u1ebf \u0111\u1ed9 nh\u1eb9...\";\n\n\n                segmentationPipeline =\n                    await pipeline(\n                        \"image-segmentation\",\n                        MODEL,\n                        {\n                            device:\n                                \"wasm\",\n\n                            dtype:\n                                \"q8\"\n                        }\n                    );\n\n\n                aiReady =\n                    true;\n\n\n                aiProgress.style.display =\n                    \"none\";\n\n\n                setStatus(\n                    \"AI \u0111\u00e3 s\u1eb5n s\u00e0ng\",\n                    \"success\"\n                );\n\n\n                return true;\n\n\n            } catch (\n                fallbackError\n            ) {\n\n                console.error(\n                    fallbackError\n                );\n\n            }\n\n        }\n\n\n        aiProgress.style.display =\n            \"none\";\n\n\n        setStatus(\n            \"Kh\u00f4ng th\u1ec3 t\u1ea3i model AI\",\n            \"error\"\n        );\n\n\n        return false;\n\n    }\n\n}\n\n\n\/* =========================================================\n   STATUS\n========================================================= *\/\n\nfunction setStatus(\n    text,\n    type = \"normal\"\n) {\n\n    status.textContent =\n        text;\n\n\n    if (\n        type === \"error\"\n    ) {\n\n        status.style.background =\n            \"#fee2e2\";\n\n        status.style.color =\n            \"#991b1b\";\n\n\n    } else if (\n        type === \"success\"\n    ) {\n\n        status.style.background =\n            \"#dcfce7\";\n\n        status.style.color =\n            \"#166534\";\n\n\n    } else if (\n        type === \"loading\"\n    ) {\n\n        status.style.background =\n            \"#fef3c7\";\n\n        status.style.color =\n            \"#92400e\";\n\n\n    } else {\n\n        status.style.background =\n            \"#f3f4f6\";\n\n        status.style.color =\n            \"#374151\";\n\n    }\n\n}\n\n\n\/* =========================================================\n   FILE UPLOAD\n========================================================= *\/\n\nfileInput.addEventListener(\n    \"change\",\n    async function (\n        event\n    ) {\n\n        const file =\n            event.target.files &&\n            event.target.files[0];\n\n\n        if (!file) {\n            return;\n        }\n\n\n        if (\n            !file.type.startsWith(\n                \"image\/\"\n            )\n        ) {\n\n            setStatus(\n                \"File kh\u00f4ng ph\u1ea3i h\u00ecnh \u1ea3nh\",\n                \"error\"\n            );\n\n            return;\n\n        }\n\n\n        const reader =\n            new FileReader();\n\n\n        reader.onload =\n            function (e) {\n\n                image =\n                    new Image();\n\n\n                image.onload =\n                    function () {\n\n                        setupImage();\n\n                    };\n\n\n                image.src =\n                    e.target.result;\n\n            };\n\n\n        reader.readAsDataURL(\n            file\n        );\n\n    }\n);\n\n\n\/* =========================================================\n   SETUP IMAGE\n========================================================= *\/\n\nfunction setupImage() {\n\n    imageLoaded =\n        true;\n\n\n    sourceDataURL =\n        image.src;\n\n\n    canvas.width =\n        image.naturalWidth;\n\n\n    canvas.height =\n        image.naturalHeight;\n\n\n    maskCanvas.width =\n        image.naturalWidth;\n\n\n    maskCanvas.height =\n        image.naturalHeight;\n\n\n    ctx.clearRect(\n        0,\n        0,\n        canvas.width,\n        canvas.height\n    );\n\n\n    ctx.drawImage(\n        image,\n        0,\n        0\n    );\n\n\n    originalImageData =\n        ctx.getImageData(\n            0,\n            0,\n            canvas.width,\n            canvas.height\n        );\n\n\n    currentImageData =\n        new ImageData(\n            new Uint8ClampedArray(\n                originalImageData.data\n            ),\n            canvas.width,\n            canvas.height\n        );\n\n\n    canvas.style.display =\n        \"block\";\n\n\n    empty.style.display =\n        \"none\";\n\n\n    dimensions.textContent =\n        image.naturalWidth +\n        \" \u00d7 \" +\n        image.naturalHeight;\n\n\n    mode.textContent =\n        \"\u1ea2nh g\u1ed1c\";\n\n\n    aiBtn.disabled =\n        false;\n\n\n    fullBtn.disabled =\n        false;\n\n\n    backgroundBtn.disabled =\n        true;\n\n\n    originalBtn.disabled =\n        false;\n\n\n    resetBtn.disabled =\n        false;\n\n\n    downloadBtn.disabled =\n        false;\n\n\n    objectsCard.style.display =\n        \"none\";\n\n\n    maskCard.style.display =\n        \"none\";\n\n\n    generatedMask =\n        null;\n\n\n    aiResults =\n        [];\n\n\n    selectedResults =\n        [];\n\n\n    history =\n        [];\n\n\n    historyIndex =\n        -1;\n\n\n    saveHistory();\n\n\n    setStatus(\n        \"\u0110\u00e3 t\u1ea3i \u1ea3nh\",\n        \"success\"\n    );\n\n}\n\n\n\/* =========================================================\n   AI\n========================================================= *\/\n\naiBtn.addEventListener(\n    \"click\",\n    async function () {\n\n        if (!imageLoaded) {\n            return;\n        }\n\n\n        aiBtn.disabled =\n            true;\n\n\n        aiProgress.style.display =\n            \"flex\";\n\n\n        progressText.textContent =\n            \"\u0110ang chu\u1ea9n b\u1ecb AI...\";\n\n\n        try {\n\n            if (!pipeline) {\n\n                const libraryOK =\n                    await loadLibrary();\n\n\n                if (!libraryOK) {\n\n                    throw new Error(\n                        \"Kh\u00f4ng t\u1ea3i \u0111\u01b0\u1ee3c th\u01b0 vi\u1ec7n AI.\"\n                    );\n\n                }\n\n            }\n\n\n            const modelOK =\n                await loadModel();\n\n\n            if (!modelOK) {\n\n                throw new Error(\n                    \"Kh\u00f4ng t\u1ea3i \u0111\u01b0\u1ee3c model AI.\"\n                );\n\n            }\n\n\n            progressText.textContent =\n                \"AI \u0111ang ph\u00e2n t\u00edch \u1ea3nh...\";\n\n\n            const result =\n                await segmentationPipeline(\n                    canvas\n                );\n\n\n            console.log(\n                \"AI segmentation result:\",\n                result\n            );\n\n\n            if (\n                !Array.isArray(\n                    result\n                ) ||\n                result.length === 0\n            ) {\n\n                throw new Error(\n                    \"AI kh\u00f4ng tr\u1ea3 v\u1ec1 segmentation.\"\n                );\n\n            }\n\n\n            aiResults =\n                normalizeResults(\n                    result\n                );\n\n\n            if (\n                aiResults.length === 0\n            ) {\n\n                throw new Error(\n                    \"AI kh\u00f4ng nh\u1eadn di\u1ec7n \u0111\u01b0\u1ee3c v\u00f9ng ch\u1ee7 th\u1ec3.\"\n                );\n\n            }\n\n\n            renderObjects();\n\n\n            objectsCard.style.display =\n                \"block\";\n\n\n            aiProgress.style.display =\n                \"none\";\n\n\n            aiBtn.disabled =\n                false;\n\n\n            setStatus(\n                \"AI \u0111\u00e3 nh\u1eadn di\u1ec7n \" +\n                aiResults.length +\n                \" v\u00f9ng\",\n                \"success\"\n            );\n\n\n        } catch (error) {\n\n            console.error(\n                \"SEGMENTATION ERROR:\",\n                error\n            );\n\n\n            aiProgress.style.display =\n                \"none\";\n\n\n            aiBtn.disabled =\n                false;\n\n\n            setStatus(\n                \"AI kh\u00f4ng t\u1ea1o \u0111\u01b0\u1ee3c mask\",\n                \"error\"\n            );\n\n\n            alert(\n                \"Kh\u00f4ng th\u1ec3 t\u1ea1o mask AI.\\n\\n\" +\n                error.message\n            );\n\n        }\n\n    }\n);\n\n\n\/* =========================================================\n   NORMALIZE RESULTS\n========================================================= *\/\n\nfunction normalizeResults(\n    result\n) {\n\n    const output =\n        [];\n\n\n    for (\n        let i = 0;\n        i < result.length;\n        i++\n    ) {\n\n        const item =\n            result[i];\n\n\n        if (!item) {\n            continue;\n        }\n\n\n        let mask =\n            item.mask;\n\n\n        if (\n            !mask ||\n            !mask.data ||\n            !mask.width ||\n            !mask.height\n        ) {\n\n            console.warn(\n                \"B\u1ecf qua k\u1ebft qu\u1ea3 kh\u00f4ng c\u00f3 mask:\",\n                item\n            );\n\n            continue;\n\n        }\n\n\n        const label =\n            String(\n                item.label ||\n                \"V\u00f9ng kh\u00f4ng x\u00e1c \u0111\u1ecbnh\"\n            );\n\n\n        const score =\n            Number(\n                item.score ||\n                0\n            );\n\n\n        output.push({\n\n            id:\n                i,\n\n            label:\n                label,\n\n            score:\n                score,\n\n            mask:\n                mask\n\n        });\n\n    }\n\n\n    return output;\n\n}\n\n\n\/* =========================================================\n   OBJECT LIST\n========================================================= *\/\n\nfunction renderObjects() {\n\n    objectsBox.innerHTML =\n        \"\";\n\n\n    selectedResults =\n        [];\n\n\n    aiResults.forEach(\n        function (\n            item,\n            index\n        ) {\n\n            const row =\n                document.createElement(\n                    \"label\"\n                );\n\n\n            row.className =\n                \"aib31-object\";\n\n\n            const checkbox =\n                document.createElement(\n                    \"input\"\n                );\n\n\n            checkbox.type =\n                \"checkbox\";\n\n\n            checkbox.checked =\n                index === 0;\n\n\n            checkbox.dataset.index =\n                String(\n                    index\n                );\n\n\n            checkbox.addEventListener(\n                \"change\",\n                function () {\n\n                    updateSelectedResults();\n\n                }\n            );\n\n\n            const info =\n                document.createElement(\n                    \"div\"\n                );\n\n\n            info.className =\n                \"aib31-object-info\";\n\n\n            const name =\n                document.createElement(\n                    \"div\"\n                );\n\n\n            name.className =\n                \"aib31-object-name\";\n\n\n            name.textContent =\n                translateLabel(\n                    item.label\n                );\n\n\n            const score =\n                document.createElement(\n                    \"div\"\n                );\n\n\n            score.className =\n                \"aib31-object-score\";\n\n\n            score.textContent =\n                \"\u0110\u1ed9 tin c\u1eady: \" +\n                Math.round(\n                    item.score * 100\n                ) +\n                \"%\";\n\n\n            info.appendChild(\n                name\n            );\n\n\n            info.appendChild(\n                score\n            );\n\n\n            row.appendChild(\n                checkbox\n            );\n\n\n            row.appendChild(\n                info\n            );\n\n\n            objectsBox.appendChild(\n                row\n            );\n\n        }\n    );\n\n\n    updateSelectedResults();\n\n}\n\n\n\/* =========================================================\n   TRANSLATION\n========================================================= *\/\n\nfunction translateLabel(\n    label\n) {\n\n    const map = {\n\n        person:\n            \"\ud83d\udc64 Ng\u01b0\u1eddi\",\n\n        car:\n            \"\ud83d\ude97 \u00d4 t\u00f4\",\n\n        truck:\n            \"\ud83d\ude9a Xe t\u1ea3i\",\n\n        bus:\n            \"\ud83d\ude8c Xe bu\u00fdt\",\n\n        motorcycle:\n            \"\ud83c\udfcd\ufe0f Xe m\u00e1y\",\n\n        motorbike:\n            \"\ud83c\udfcd\ufe0f Xe m\u00e1y\",\n\n        bicycle:\n            \"\ud83d\udeb2 Xe \u0111\u1ea1p\",\n\n        dog:\n            \"\ud83d\udc15 Ch\u00f3\",\n\n        cat:\n            \"\ud83d\udc08 M\u00e8o\",\n\n        bird:\n            \"\ud83d\udc26 Chim\",\n\n        horse:\n            \"\ud83d\udc0e Ng\u1ef1a\",\n\n        cow:\n            \"\ud83d\udc04 B\u00f2\",\n\n        sheep:\n            \"\ud83d\udc11 C\u1eebu\",\n\n        boat:\n            \"\u26f5 Thuy\u1ec1n\",\n\n        airplane:\n            \"\u2708\ufe0f M\u00e1y bay\",\n\n        aeroplane:\n            \"\u2708\ufe0f M\u00e1y bay\",\n\n        train:\n            \"\ud83d\ude86 T\u00e0u\",\n\n        table:\n            \"\ud83e\ude91 B\u00e0n\",\n\n        chair:\n            \"\ud83e\ude91 Gh\u1ebf\",\n\n        sofa:\n            \"\ud83d\udecb\ufe0f Sofa\",\n\n        bed:\n            \"\ud83d\udecf\ufe0f Gi\u01b0\u1eddng\",\n\n        television:\n            \"\ud83d\udcfa Tivi\",\n\n        laptop:\n            \"\ud83d\udcbb Laptop\",\n\n        computer:\n            \"\ud83d\udcbb M\u00e1y t\u00ednh\",\n\n        phone:\n            \"\ud83d\udcf1 \u0110i\u1ec7n tho\u1ea1i\",\n\n        bottle:\n            \"\ud83c\udf7e Chai\",\n\n        cup:\n            \"\u2615 C\u1ed1c\",\n\n        plant:\n            \"\ud83c\udf31 C\u00e2y\",\n\n        tree:\n            \"\ud83c\udf33 C\u00e2y\",\n\n        flower:\n            \"\ud83c\udf38 Hoa\"\n\n    };\n\n\n    const key =\n        label\n            .toLowerCase()\n            .trim();\n\n\n    return map[key] ||\n        (\n            \"\ud83d\udd39 \" +\n            label\n        );\n\n}\n\n\n\/* =========================================================\n   SELECT\n========================================================= *\/\n\nfunction updateSelectedResults() {\n\n    selectedResults =\n        [];\n\n\n    const boxes =\n        objectsBox.querySelectorAll(\n            \"input[type=checkbox]\"\n        );\n\n\n    boxes.forEach(\n        function (\n            box\n        ) {\n\n            if (\n                box.checked\n            ) {\n\n                const index =\n                    Number(\n                        box.dataset.index\n                    );\n\n\n                if (\n                    aiResults[index]\n                ) {\n\n                    selectedResults.push(\n                        aiResults[index]\n                    );\n\n                }\n\n            }\n\n        }\n    );\n\n\n    backgroundBtn.disabled =\n        selectedResults.length === 0;\n\n}\n\n\n\/* =========================================================\n   MASK BUTTON\n========================================================= *\/\n\nmaskBtn.addEventListener(\n    \"click\",\n    function () {\n\n        updateSelectedResults();\n\n\n        if (\n            selectedResults.length === 0\n        ) {\n\n            alert(\n                \"H\u00e3y ch\u1ecdn \u00edt nh\u1ea5t m\u1ed9t ch\u1ee7 th\u1ec3.\"\n            );\n\n            return;\n\n        }\n\n\n        try {\n\n            createCombinedMask();\n\n\n            if (!generatedMask) {\n\n                throw new Error(\n                    \"Mask r\u1ed7ng.\"\n                );\n\n            }\n\n\n            showMaskPreview();\n\n\n            maskCard.style.display =\n                \"block\";\n\n\n            backgroundBtn.disabled =\n                false;\n\n\n            setStatus(\n                \"Mask \u0111\u00e3 t\u1ea1o th\u00e0nh c\u00f4ng\",\n                \"success\"\n            );\n\n\n        } catch (error) {\n\n            console.error(\n                error\n            );\n\n\n            generatedMask =\n                null;\n\n\n            backgroundBtn.disabled =\n                true;\n\n\n            setStatus(\n                \"Kh\u00f4ng t\u1ea1o \u0111\u01b0\u1ee3c mask\",\n                \"error\"\n            );\n\n\n            alert(\n                \"Kh\u00f4ng th\u1ec3 t\u1ea1o mask.\\n\\n\" +\n                error.message\n            );\n\n        }\n\n    }\n);\n\n\n\/* =========================================================\n   CREATE MASK\n========================================================= *\/\n\nfunction createCombinedMask() {\n\n    if (\n        selectedResults.length === 0\n    ) {\n\n        throw new Error(\n            \"Kh\u00f4ng c\u00f3 ch\u1ee7 th\u1ec3 \u0111\u01b0\u1ee3c ch\u1ecdn.\"\n        );\n\n    }\n\n\n    const W =\n        canvas.width;\n\n\n    const H =\n        canvas.height;\n\n\n    const combined =\n        new Uint8ClampedArray(\n            W * H\n        );\n\n\n    combined.fill(0);\n\n\n    for (\n        const item of selectedResults\n    ) {\n\n        const mask =\n            item.mask;\n\n\n        if (\n            !mask ||\n            !mask.data\n        ) {\n            continue;\n        }\n\n\n        const mw =\n            mask.width;\n\n\n        const mh =\n            mask.height;\n\n\n        const data =\n            mask.data;\n\n\n        const channels =\n            Math.max(\n                1,\n                Math.floor(\n                    data.length \/\n                    (mw * mh)\n                )\n            );\n\n\n        for (\n            let y = 0;\n            y < H;\n            y++\n        ) {\n\n            const sy =\n                Math.min(\n                    mh - 1,\n                    Math.floor(\n                        y * mh \/ H\n                    )\n                );\n\n\n            for (\n                let x = 0;\n                x < W;\n                x++\n            ) {\n\n                const sx =\n                    Math.min(\n                        mw - 1,\n                        Math.floor(\n                            x * mw \/ W\n                        )\n                    );\n\n\n                const index =\n                    sy * mw +\n                    sx;\n\n\n                let value =\n                    0;\n\n\n                if (\n                    channels === 1\n                ) {\n\n                    value =\n                        data[index];\n\n                } else {\n\n                    value =\n                        data[\n                            index *\n                            channels\n                        ];\n\n                }\n\n\n                const dest =\n                    y * W +\n                    x;\n\n\n                if (\n                    value >\n                    combined[dest]\n                ) {\n\n                    combined[dest] =\n                        value;\n\n                }\n\n            }\n\n        }\n\n    }\n\n\n    let nonZero =\n        0;\n\n\n    for (\n        let i = 0;\n        i < combined.length;\n        i++\n    ) {\n\n        if (\n            combined[i] > 20\n        ) {\n\n            nonZero++;\n\n\n            if (\n                nonZero > 100\n            ) {\n\n                break;\n\n            }\n\n        }\n\n    }\n\n\n    if (\n        nonZero <= 100\n    ) {\n\n        throw new Error(\n            \"Mask AI qu\u00e1 nh\u1ecf ho\u1eb7c r\u1ed7ng.\"\n        );\n\n    }\n\n\n    generatedMask =\n        combined;\n\n}\n\n\n\/* =========================================================\n   SHOW MASK\n========================================================= *\/\n\nfunction showMaskPreview() {\n\n    const W =\n        canvas.width;\n\n\n    const H =\n        canvas.height;\n\n\n    const imageData =\n        maskCtx.createImageData(\n            W,\n            H\n        );\n\n\n    const data =\n        imageData.data;\n\n\n    const sensitivity =\n        Number(\n            threshold.value\n        ) \/ 100;\n\n\n    for (\n        let i = 0;\n        i < generatedMask.length;\n        i++\n    ) {\n\n        const value =\n            generatedMask[i];\n\n\n        const alpha =\n            value >=\n            sensitivity * 255\n                ? 255\n                : 0;\n\n\n        const p =\n            i * 4;\n\n\n        if (alpha) {\n\n            data[p] =\n                255;\n\n            data[p + 1] =\n                255;\n\n            data[p + 2] =\n                255;\n\n            data[p + 3] =\n                255;\n\n        } else {\n\n            data[p] =\n                20;\n\n            data[p + 1] =\n                20;\n\n            data[p + 2] =\n                20;\n\n            data[p + 3] =\n                255;\n\n        }\n\n    }\n\n\n    maskCtx.putImageData(\n        imageData,\n        0,\n        0\n    );\n\n\n    mode.textContent =\n        \"Xem tr\u01b0\u1edbc Mask AI\";\n\n}\n\n\n\/* =========================================================\n   THRESHOLD\n========================================================= *\/\n\nthreshold.addEventListener(\n    \"input\",\n    function () {\n\n        thresholdValue.textContent =\n            threshold.value +\n            \"%\";\n\n\n        if (\n            generatedMask\n        ) {\n\n            showMaskPreview();\n\n        }\n\n    }\n);\n\n\n\/* =========================================================\n   BLUR RANGE\n========================================================= *\/\n\nblurRange.addEventListener(\n    \"input\",\n    function () {\n\n        blurValue.textContent =\n            blurRange.value +\n            \"px\";\n\n    }\n);\n\n\n\/* =========================================================\n   BACKGROUND BLUR\n========================================================= *\/\n\nbackgroundBtn.addEventListener(\n    \"click\",\n    function () {\n\n        if (\n            !generatedMask ||\n            generatedMask.length === 0\n        ) {\n\n            alert(\n                \"Ch\u01b0a c\u00f3 mask AI.\"\n            );\n\n            return;\n\n        }\n\n\n        let visible =\n            0;\n\n\n        for (\n            let i = 0;\n            i < generatedMask.length;\n            i += 10\n        ) {\n\n            if (\n                generatedMask[i] > 20\n            ) {\n\n                visible++;\n\n\n                if (\n                    visible > 20\n                ) {\n\n                    break;\n\n                }\n\n            }\n\n        }\n\n\n        if (\n            visible === 0\n        ) {\n\n            alert(\n                \"Mask AI kh\u00f4ng h\u1ee3p l\u1ec7. Kh\u00f4ng th\u1ef1c hi\u1ec7n l\u00e0m m\u1edd.\"\n            );\n\n            return;\n\n        }\n\n\n        applyBackgroundBlur();\n\n    }\n);\n\n\n\/* =========================================================\n   APPLY BACKGROUND BLUR\n========================================================= *\/\n\nfunction applyBackgroundBlur() {\n\n    const W =\n        canvas.width;\n\n\n    const H =\n        canvas.height;\n\n\n    const blurAmount =\n        Number(\n            blurRange.value\n        );\n\n\n    const blurCanvas =\n        document.createElement(\n            \"canvas\"\n        );\n\n\n    blurCanvas.width =\n        W;\n\n\n    blurCanvas.height =\n        H;\n\n\n    const bctx =\n        blurCanvas.getContext(\n            \"2d\"\n        );\n\n\n    bctx.filter =\n        \"blur(\" +\n        blurAmount +\n        \"px)\";\n\n\n    bctx.drawImage(\n        canvas,\n        0,\n        0\n    );\n\n\n    bctx.filter =\n        \"none\";\n\n\n    const finalCanvas =\n        document.createElement(\n            \"canvas\"\n        );\n\n\n    finalCanvas.width =\n        W;\n\n\n    finalCanvas.height =\n        H;\n\n\n    const fctx =\n        finalCanvas.getContext(\n            \"2d\"\n        );\n\n\n    fctx.drawImage(\n        blurCanvas,\n        0,\n        0\n    );\n\n\n    const maskImage =\n        document.createElement(\n            \"canvas\"\n        );\n\n\n    maskImage.width =\n        W;\n\n\n    maskImage.height =\n        H;\n\n\n    const mctx =\n        maskImage.getContext(\n            \"2d\"\n        );\n\n\n    const md =\n        mctx.createImageData(\n            W,\n            H\n        );\n\n\n    const sensitivity =\n        Number(\n            threshold.value\n        ) \/ 100;\n\n\n    for (\n        let i = 0;\n        i < generatedMask.length;\n        i++\n    ) {\n\n        const p =\n            i * 4;\n\n\n        const alpha =\n            generatedMask[i] >=\n            sensitivity * 255\n                ? 255\n                : 0;\n\n\n        md.data[p] =\n            255;\n\n\n        md.data[p + 1] =\n            255;\n\n\n        md.data[p + 2] =\n            255;\n\n\n        md.data[p + 3] =\n            alpha;\n\n    }\n\n\n    mctx.putImageData(\n        md,\n        0,\n        0\n    );\n\n\n    const originalCanvas =\n        document.createElement(\n            \"canvas\"\n        );\n\n\n    originalCanvas.width =\n        W;\n\n\n    originalCanvas.height =\n        H;\n\n\n    const octx =\n        originalCanvas.getContext(\n            \"2d\"\n        );\n\n\n    octx.putImageData(\n        originalImageData,\n        0,\n        0\n    );\n\n\n    const subjectCanvas =\n        document.createElement(\n            \"canvas\"\n        );\n\n\n    subjectCanvas.width =\n        W;\n\n\n    subjectCanvas.height =\n        H;\n\n\n    const sctx =\n        subjectCanvas.getContext(\n            \"2d\"\n        );\n\n\n    sctx.drawImage(\n        originalCanvas,\n        0,\n        0\n    );\n\n\n    sctx.globalCompositeOperation =\n        \"destination-in\";\n\n\n    sctx.drawImage(\n        maskImage,\n        0,\n        0\n    );\n\n\n    fctx.drawImage(\n        subjectCanvas,\n        0,\n        0\n    );\n\n\n    ctx.clearRect(\n        0,\n        0,\n        W,\n        H\n    );\n\n\n    ctx.drawImage(\n        finalCanvas,\n        0,\n        0\n    );\n\n\n    currentImageData =\n        ctx.getImageData(\n            0,\n            0,\n            W,\n            H\n        );\n\n\n    mode.textContent =\n        \"\u0110\u00e3 l\u00e0m m\u1edd n\u1ec1n\";\n\n\n    setStatus(\n        \"\u0110\u00e3 l\u00e0m m\u1edd n\u1ec1n theo AI\",\n        \"success\"\n    );\n\n\n    saveHistory();\n\n}\n\n\n\/* =========================================================\n   FULL IMAGE BLUR\n========================================================= *\/\n\nfullBtn.addEventListener(\n    \"click\",\n    function () {\n\n        if (\n            !imageLoaded\n        ) {\n            return;\n        }\n\n\n        const W =\n            canvas.width;\n\n\n        const H =\n            canvas.height;\n\n\n        const temp =\n            document.createElement(\n                \"canvas\"\n            );\n\n\n        temp.width =\n            W;\n\n\n        temp.height =\n            H;\n\n\n        const tctx =\n            temp.getContext(\n                \"2d\"\n            );\n\n\n        tctx.filter =\n            \"blur(\" +\n            Number(\n                blurRange.value\n            ) +\n            \"px)\";\n\n\n        tctx.drawImage(\n            canvas,\n            0,\n            0\n        );\n\n\n        tctx.filter =\n            \"none\";\n\n\n        ctx.clearRect(\n            0,\n            0,\n            W,\n            H\n        );\n\n\n        ctx.drawImage(\n            temp,\n            0,\n            0\n        );\n\n\n        currentImageData =\n            ctx.getImageData(\n                0,\n                0,\n                W,\n                H\n            );\n\n\n        mode.textContent =\n            \"L\u00e0m m\u1edd to\u00e0n \u1ea3nh\";\n\n\n        setStatus(\n            \"\u0110\u00e3 l\u00e0m m\u1edd to\u00e0n \u1ea3nh\",\n            \"success\"\n        );\n\n\n        saveHistory();\n\n    }\n);\n\n\n\/* =========================================================\n   ORIGINAL\n========================================================= *\/\n\noriginalBtn.addEventListener(\n    \"click\",\n    function () {\n\n        if (\n            !originalImageData\n        ) {\n            return;\n        }\n\n\n        ctx.putImageData(\n            originalImageData,\n            0,\n            0\n        );\n\n\n        currentImageData =\n            new ImageData(\n                new Uint8ClampedArray(\n                    originalImageData.data\n                ),\n                originalImageData.width,\n                originalImageData.height\n            );\n\n\n        mode.textContent =\n            \"\u1ea2nh g\u1ed1c\";\n\n\n        setStatus(\n            \"\u0110\u00e3 hi\u1ec7n l\u1ea1i \u1ea3nh g\u1ed1c\",\n            \"success\"\n        );\n\n\n        saveHistory();\n\n    }\n);\n\n\n\/* =========================================================\n   HISTORY\n========================================================= *\/\n\nfunction saveHistory() {\n\n    if (\n        !currentImageData\n    ) {\n        return;\n    }\n\n\n    if (\n        historyIndex <\n        history.length - 1\n    ) {\n\n        history =\n            history.slice(\n                0,\n                historyIndex + 1\n            );\n\n    }\n\n\n    const copy =\n        new ImageData(\n            new Uint8ClampedArray(\n                currentImageData.data\n            ),\n            currentImageData.width,\n            currentImageData.height\n        );\n\n\n    history.push(\n        copy\n    );\n\n\n    if (\n        history.length > 10\n    ) {\n\n        history.shift();\n\n    }\n\n\n    historyIndex =\n        history.length - 1;\n\n\n    updateHistoryButtons();\n\n}\n\n\n\/* =========================================================\n   RESTORE HISTORY\n========================================================= *\/\n\nfunction restoreHistory() {\n\n    if (\n        !history[historyIndex]\n    ) {\n        return;\n    }\n\n\n    const data =\n        history[historyIndex];\n\n\n    ctx.putImageData(\n        data,\n        0,\n        0\n    );\n\n\n    currentImageData =\n        new ImageData(\n            new Uint8ClampedArray(\n                data.data\n            ),\n            data.width,\n            data.height\n        );\n\n\n    mode.textContent =\n        \"B\u01b0\u1edbc ch\u1ec9nh s\u1eeda\";\n\n\n    updateHistoryButtons();\n\n}\n\n\n\/* =========================================================\n   UNDO\n========================================================= *\/\n\nundoBtn.addEventListener(\n    \"click\",\n    function () {\n\n        if (\n            historyIndex <= 0\n        ) {\n            return;\n        }\n\n\n        historyIndex--;\n\n\n        restoreHistory();\n\n\n        setStatus(\n            \"\u0110\u00e3 ho\u00e0n t\u00e1c\",\n            \"success\"\n        );\n\n    }\n);\n\n\n\/* =========================================================\n   REDO\n========================================================= *\/\n\nredoBtn.addEventListener(\n    \"click\",\n    function () {\n\n        if (\n            historyIndex >=\n            history.length - 1\n        ) {\n            return;\n        }\n\n\n        historyIndex++;\n\n\n        restoreHistory();\n\n\n        setStatus(\n            \"\u0110\u00e3 l\u00e0m l\u1ea1i\",\n            \"success\"\n        );\n\n    }\n);\n\n\n\/* =========================================================\n   HISTORY BUTTONS\n========================================================= *\/\n\nfunction updateHistoryButtons() {\n\n    undoBtn.disabled =\n        historyIndex <= 0;\n\n\n    redoBtn.disabled =\n        historyIndex >=\n        history.length - 1;\n\n}\n\n\n\/* =========================================================\n   RESET\n========================================================= *\/\n\nresetBtn.addEventListener(\n    \"click\",\n    function () {\n\n        if (\n            !originalImageData\n        ) {\n            return;\n        }\n\n\n        ctx.putImageData(\n            originalImageData,\n            0,\n            0\n        );\n\n\n        currentImageData =\n            new ImageData(\n                new Uint8ClampedArray(\n                    originalImageData.data\n                ),\n                originalImageData.width,\n                originalImageData.height\n            );\n\n\n        aiResults =\n            [];\n\n\n        selectedResults =\n            [];\n\n\n        generatedMask =\n            null;\n\n\n        objectsBox.innerHTML =\n            \"\";\n\n\n        objectsCard.style.display =\n            \"none\";\n\n\n        maskCard.style.display =\n            \"none\";\n\n\n        backgroundBtn.disabled =\n            true;\n\n\n        history =\n            [];\n\n\n        historyIndex =\n            -1;\n\n\n        saveHistory();\n\n\n        mode.textContent =\n            \"\u1ea2nh g\u1ed1c\";\n\n\n        setStatus(\n            \"\u0110\u00e3 reset\",\n            \"success\"\n        );\n\n    }\n);\n\n\n\/* =========================================================\n   DOWNLOAD\n========================================================= *\/\n\ndownloadBtn.addEventListener(\n    \"click\",\n    function () {\n\n        if (\n            !imageLoaded\n        ) {\n            return;\n        }\n\n\n        const mime =\n            format.value;\n\n\n        let extension =\n            \"png\";\n\n\n        if (\n            mime ===\n            \"image\/jpeg\"\n        ) {\n\n            extension =\n                \"jpg\";\n\n        } else if (\n            mime ===\n            \"image\/webp\"\n        ) {\n\n            extension =\n                \"webp\";\n\n        }\n\n\n        canvas.toBlob(\n            function (blob) {\n\n                if (!blob) {\n\n                    alert(\n                        \"Kh\u00f4ng th\u1ec3 t\u1ea1o file \u1ea3nh.\"\n                    );\n\n                    return;\n\n                }\n\n\n                const url =\n                    URL.createObjectURL(\n                        blob\n                    );\n\n\n                const a =\n                    document.createElement(\n                        \"a\"\n                    );\n\n\n                a.href =\n                    url;\n\n\n                a.download =\n                    \"ai-blur-\" +\n                    Date.now() +\n                    \".\" +\n                    extension;\n\n\n                document.body.appendChild(\n                    a\n                );\n\n\n                a.click();\n\n\n                a.remove();\n\n\n                setTimeout(\n                    function () {\n\n                        URL.revokeObjectURL(\n                            url\n                        );\n\n                    },\n                    1000\n                );\n\n            },\n            mime,\n            mime ===\n            \"image\/jpeg\"\n                ? 0.92\n                : undefined\n        );\n\n    }\n);\n\n\n\/* =========================================================\n   INITIAL\n========================================================= *\/\n\nsetStatus(\n    \"S\u1eb5n s\u00e0ng \u2013 h\u00e3y ch\u1ecdn \u1ea3nh\"\n);\n\n})();\n\n<\/script>\n\n    \n<\/div><\/div><\/div><\/div><\/div><\/div><div class=\"vc_row_inner tdi_14  vc_row vc_inner wpb_row td-pb-row\" >\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_14{\r\n                    position: relative !important;\r\n                    top: 0;\r\n                    transform: none;\r\n                    -webkit-transform: none;\r\n                }.tdi_14,\r\n\t\t\t\t.tdi_14 .tdc-inner-columns{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_14 .tdc-inner-columns{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}\n<\/style><div class=\"vc_column_inner tdi_16  wpb_column vc_column_container tdc-inner-column td-pb-span12\">\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_16{\r\n                    vertical-align: baseline;\r\n                }.tdi_16 .vc_column-inner > .wpb_wrapper,\r\n\t\t\t\t.tdi_16 .vc_column-inner > .wpb_wrapper .tdc-elements{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_16 .vc_column-inner > .wpb_wrapper .tdc-elements{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}\n<\/style><div class=\"vc_column-inner\"><div class=\"wpb_wrapper\" ><\/div><\/div><\/div><\/div><\/div><\/div><\/div><\/div><div id=\"tdi_17\" class=\"tdc-row\"><div class=\"vc_row tdi_18  wpb_row td-pb-row\" >\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_18,\r\n                .tdi_18 .tdc-columns{\r\n                    min-height: 0;\r\n                }.tdi_18,\r\n\t\t\t\t.tdi_18 .tdc-columns{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_18 .tdc-columns{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}.tdi_18:before,\r\n\t\t\t\t.tdi_18:after{\r\n\t\t\t\t    display: table;\r\n\t\t\t\t}\n<\/style><div class=\"vc_column tdi_20  wpb_column vc_column_container tdc-column td-pb-span12\">\n<style scoped>\n\/* custom css - generated by TagDiv Composer *\/\n\n\/* custom css - generated by TagDiv Composer *\/\n.tdi_20{\r\n                    vertical-align: baseline;\r\n                }.tdi_20 > .wpb_wrapper,\r\n\t\t\t\t.tdi_20 > .wpb_wrapper > .tdc-elements{\r\n\t\t\t\t    display: block;\r\n\t\t\t\t}.tdi_20 > .wpb_wrapper > .tdc-elements{\r\n\t\t\t\t    width: 100%;\r\n\t\t\t\t}.tdi_20 > .wpb_wrapper > .vc_row_inner{\r\n\t\t\t\t    width: auto;\r\n\t\t\t\t}.tdi_20 > .wpb_wrapper{\r\n\t\t\t\t    width: auto;\r\n\t\t\t\t    height: auto;\r\n\t\t\t\t}\n<\/style><div class=\"wpb_wrapper\" ><\/div><\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":678,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-612","page","type-page","status-publish","has-post-thumbnail"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3 | App Mitunet<\/title>\n<meta name=\"description\" content=\"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online \u0111\u01a1n gi\u1ea3n m\u00e0 hi\u1ec7u qu\u1ea3, c\u00e1ch l\u00e0m m\u1edd n\u1ec1n h\u00ecnh \u1ea3nh b\u1eb1ng AI, gi\u1ea3i ph\u00e1p l\u00e0m cho n\u1ec1n h\u00ecnh \u1ea3nh m\u1edd \u0111i nh\u01b0ng v\u1eabn gi\u1eef l\u1ea1i ch\u1ee7 th\u1ec3 ch\u00ednh...\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/\" \/>\n<meta property=\"og:locale\" content=\"vi_VN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3 | App Mitunet\" \/>\n<meta property=\"og:description\" content=\"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online \u0111\u01a1n gi\u1ea3n m\u00e0 hi\u1ec7u qu\u1ea3, c\u00e1ch l\u00e0m m\u1edd n\u1ec1n h\u00ecnh \u1ea3nh b\u1eb1ng AI, gi\u1ea3i ph\u00e1p l\u00e0m cho n\u1ec1n h\u00ecnh \u1ea3nh m\u1edd \u0111i nh\u01b0ng v\u1eabn gi\u1eef l\u1ea1i ch\u1ee7 th\u1ec3 ch\u00ednh...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/\" \/>\n<meta property=\"og:site_name\" content=\"App Mitunet\" \/>\n<meta property=\"article:modified_time\" content=\"2026-08-15T11:21:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/app.mitunet.com\/home\/wp-content\/uploads\/2026\/08\/lam-mo-nen-anh-online.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 ph\u00fat\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/\",\"url\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/\",\"name\":\"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3 | App Mitunet\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/lam-mo-nen-anh-online.jpg\",\"datePublished\":\"2026-08-13T04:02:29+00:00\",\"dateModified\":\"2026-08-15T11:21:18+00:00\",\"description\":\"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online \u0111\u01a1n gi\u1ea3n m\u00e0 hi\u1ec7u qu\u1ea3, c\u00e1ch l\u00e0m m\u1edd n\u1ec1n h\u00ecnh \u1ea3nh b\u1eb1ng AI, gi\u1ea3i ph\u00e1p l\u00e0m cho n\u1ec1n h\u00ecnh \u1ea3nh m\u1edd \u0111i nh\u01b0ng v\u1eabn gi\u1eef l\u1ea1i ch\u1ee7 th\u1ec3 ch\u00ednh...\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/#breadcrumb\"},\"inLanguage\":\"vi\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"vi\",\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/#primaryimage\",\"url\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/lam-mo-nen-anh-online.jpg\",\"contentUrl\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/lam-mo-nen-anh-online.jpg\",\"width\":800,\"height\":600,\"caption\":\"\u1ee8ng d\u1ee5ng l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online mi\u1ec5n ph\u00ed\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/lam-mo-nen-anh\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Trang ch\u1ee7\",\"item\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/#website\",\"url\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/\",\"name\":\"App Mitunet\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/app.mitunet.com\\\/home\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"vi\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3 | App Mitunet","description":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online \u0111\u01a1n gi\u1ea3n m\u00e0 hi\u1ec7u qu\u1ea3, c\u00e1ch l\u00e0m m\u1edd n\u1ec1n h\u00ecnh \u1ea3nh b\u1eb1ng AI, gi\u1ea3i ph\u00e1p l\u00e0m cho n\u1ec1n h\u00ecnh \u1ea3nh m\u1edd \u0111i nh\u01b0ng v\u1eabn gi\u1eef l\u1ea1i ch\u1ee7 th\u1ec3 ch\u00ednh...","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/","og_locale":"vi_VN","og_type":"article","og_title":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3 | App Mitunet","og_description":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online \u0111\u01a1n gi\u1ea3n m\u00e0 hi\u1ec7u qu\u1ea3, c\u00e1ch l\u00e0m m\u1edd n\u1ec1n h\u00ecnh \u1ea3nh b\u1eb1ng AI, gi\u1ea3i ph\u00e1p l\u00e0m cho n\u1ec1n h\u00ecnh \u1ea3nh m\u1edd \u0111i nh\u01b0ng v\u1eabn gi\u1eef l\u1ea1i ch\u1ee7 th\u1ec3 ch\u00ednh...","og_url":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/","og_site_name":"App Mitunet","article_modified_time":"2026-08-15T11:21:18+00:00","og_image":[{"width":800,"height":600,"url":"https:\/\/app.mitunet.com\/home\/wp-content\/uploads\/2026\/08\/lam-mo-nen-anh-online.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"\u01af\u1edbc t\u00ednh th\u1eddi gian \u0111\u1ecdc":"1 ph\u00fat"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/","url":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/","name":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3 | App Mitunet","isPartOf":{"@id":"https:\/\/app.mitunet.com\/home\/#website"},"primaryImageOfPage":{"@id":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/#primaryimage"},"image":{"@id":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/#primaryimage"},"thumbnailUrl":"https:\/\/app.mitunet.com\/home\/wp-content\/uploads\/2026\/08\/lam-mo-nen-anh-online.jpg","datePublished":"2026-08-13T04:02:29+00:00","dateModified":"2026-08-15T11:21:18+00:00","description":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online \u0111\u01a1n gi\u1ea3n m\u00e0 hi\u1ec7u qu\u1ea3, c\u00e1ch l\u00e0m m\u1edd n\u1ec1n h\u00ecnh \u1ea3nh b\u1eb1ng AI, gi\u1ea3i ph\u00e1p l\u00e0m cho n\u1ec1n h\u00ecnh \u1ea3nh m\u1edd \u0111i nh\u01b0ng v\u1eabn gi\u1eef l\u1ea1i ch\u1ee7 th\u1ec3 ch\u00ednh...","breadcrumb":{"@id":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/#breadcrumb"},"inLanguage":"vi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/"]}]},{"@type":"ImageObject","inLanguage":"vi","@id":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/#primaryimage","url":"https:\/\/app.mitunet.com\/home\/wp-content\/uploads\/2026\/08\/lam-mo-nen-anh-online.jpg","contentUrl":"https:\/\/app.mitunet.com\/home\/wp-content\/uploads\/2026\/08\/lam-mo-nen-anh-online.jpg","width":800,"height":600,"caption":"\u1ee8ng d\u1ee5ng l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online mi\u1ec5n ph\u00ed"},{"@type":"BreadcrumbList","@id":"https:\/\/app.mitunet.com\/home\/lam-mo-nen-anh\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Trang ch\u1ee7","item":"https:\/\/app.mitunet.com\/home\/"},{"@type":"ListItem","position":2,"name":"C\u00f4ng c\u1ee5 l\u00e0m m\u1edd n\u1ec1n \u1ea3nh online chuy\u00ean nghi\u1ec7p, l\u00e0m m\u1edd h\u00ecnh \u1ea3nh n\u1ec1n hi\u1ec7u qu\u1ea3"}]},{"@type":"WebSite","@id":"https:\/\/app.mitunet.com\/home\/#website","url":"https:\/\/app.mitunet.com\/home\/","name":"App Mitunet","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/app.mitunet.com\/home\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"vi"}]}},"_links":{"self":[{"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/pages\/612","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/comments?post=612"}],"version-history":[{"count":13,"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/pages\/612\/revisions"}],"predecessor-version":[{"id":679,"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/pages\/612\/revisions\/679"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/media\/678"}],"wp:attachment":[{"href":"https:\/\/app.mitunet.com\/home\/wp-json\/wp\/v2\/media?parent=612"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}