Ignore:
Timestamp:
2021-12-08T11:05:22+13:00 (2 years ago)
Author:
cstephen
Message:

Implement thresholded image display

Location:
main/trunk/model-interfaces-dev/atea/ocr/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/model-interfaces-dev/atea/ocr/src/components/MainPage.vue

    r35762 r35769  
    1111        </div>
    1212
    13         <div v-if="imageUrl !== null" class="image-area">
     13        <div v-if="imageUrl !== null" class="main-area">
    1414            <div class="controls">
     15                <button class="btn-primary" @click="showEditor = true" :disabled="ocrInProgress">
     16                    <span class="material-icons">edit</span>
     17                    <span>{{ translations.get("MainPage_EditImage") }}</span>
     18                </button>
     19
    1520                <button class="btn-primary" @click="doOcr" :disabled="ocrInProgress">
    1621                    <span class="material-icons">play_arrow</span>
    1722                    <span>{{ translations.get("MainPage_PerformOCR") }}</span>
    18                 </button>
    19 
    20                 <button class="btn-primary" @click="showEditor = true" :disabled="ocrInProgress">
    21                     <span class="material-icons">edit</span>
    22                     <span>{{ translations.get("MainPage_EditImage") }}</span>
    2323                </button>
    2424
     
    3838            </div>
    3939
    40             <img class="image-display" :src="imageUrl" />
     40            <div class="ocr-image-container">
     41                <img class="ocr-image" :src="imageUrl" />
     42                <img v-if="showThresholdedImage" class="ocr-image" :src="thresholdedImageUrl" />
     43
     44                <div v-if="thresholdedImageUrl" class="thresholded-image-controls card">
     45                    <input id="chk-show-thresholded-image" type="checkbox" v-model="showThresholdedImage" />
     46                    <label for="chk-show-thresholded-image">{{ translations.get('MainPage_ShowThresholdedImage') }}</label>
     47
     48                    <span class="body2">{{ translations.get('MainPage_ThresholdedImageDescription') }}</span>
     49                </div>
     50            </div>
    4151
    4252            <textarea class="text-container" v-model="ocrResult" :placeholder="translations.get('MainPage_OCRHint')"
     
    103113}
    104114
    105 .image-area {
     115.main-area {
    106116    display: grid;
    107117    grid-template-columns: 1fr 1fr;
     
    122132}
    123133
    124 .image-display {
     134.ocr-image-container {
     135    position: relative;
     136    height: 100%;
     137    width: 100%;
     138
     139    display: grid;
     140    grid-template-columns: 1fr;
     141    grid-template-rows: 1fr;
     142
     143    align-items: center;
     144    justify-items: center;
     145
     146    &:hover {
     147        .thresholded-image-controls {
     148            opacity: 0.99;
     149        }
     150    }
     151}
     152
     153.ocr-image {
    125154    border: 1px solid #444;
    126155    max-width: 100%;
    127156    max-height: 80vh;
    128157    object-fit: contain;
     158    grid-row: 1;
     159    grid-column: 1;
     160}
     161
     162.thresholded-image-controls {
     163    position: absolute;
     164    top: 1em;
     165    left: 1em;
     166    max-width: 50%;
     167
     168    display: grid;
     169    grid-template-columns: auto 1fr;
     170    grid-template-rows: auto auto;
     171    align-items: center;
     172    justify-items: start;
     173    gap: 0.5em;
     174
     175    transition-duration: var(--transition-duration);
     176    opacity: 0;
     177
     178    span {
     179        grid-column: span 2;
     180    }
    129181}
    130182
     
    160212            imageBuffer: null,
    161213            imageUrl: null,
     214
     215            thresholdedImageUrl: null,
     216            showThresholdedImage: false,
     217
    162218            ocrInProgress: false,
     219            /** @type {OcrResult} */
    163220            ocrResult: null,
     221
    164222            showEditor: false,
    165223            ocrTextEdited: false
     
    226284                this.ocrResult = result[0].text;
    227285                this.ocrTextEdited = false;
     286
     287                const thresholdedImageBlob = await ocrService.getThresholdedImage(result[0].thresholdedImageKey);
     288
     289                if (this.thresholdedImageUrl !== null) {
     290                    URL.revokeObjectURL(this.thresholdedImageUrl);
     291                }
     292
     293                this.thresholdedImageUrl = URL.createObjectURL(thresholdedImageBlob);
    228294            }
    229295            catch (ex) {
     
    291357            }
    292358
    293             URL.revokeObjectURL(this.imageUrl);
    294             this.imageUrl = null;
     359            if (this.imageUrl) {
     360                URL.revokeObjectURL(this.imageUrl);
     361                this.imageUrl = null;
     362            }
     363
     364            if (this.thresholdedImageUrl) {
     365                URL.revokeObjectURL(this.thresholdedImageUrl);
     366                this.thresholdedImageUrl = null;
     367            }
     368
    295369            this.ocrInProgress = false;
    296370            this.ocrResult = null;
  • main/trunk/model-interfaces-dev/atea/ocr/src/js/OcrService.js

    r35746 r35769  
    2828}
    2929
     30export class OcrResult
     31{
     32    /**
     33     * Initializes a new instance of the {@link OcrResult} object.
     34     * @param {String} key The result key.
     35     * @param {String} text The extracted text.
     36     * @param {String} fileName The name of the file from which the text was extracted.
     37     * @param {String} thresholdedImageKey The key that can be used to retrieve the thresholded image used in the OCR process.
     38     */
     39    constructor(key, text, fileName, thresholdedImageKey)
     40    {
     41        /** @type {String} The result key. */
     42        this.key = key;
     43
     44        /** @type {String} The extracted text. */
     45        this.text = text;
     46
     47        /** @type {String} The name of the file from which the text was extracted. */
     48        this.fileName = fileName;
     49
     50        /** @type {String} The key that can be used to retrieve the thresholded image. */
     51        this.thresholdedImageKey = thresholdedImageKey;
     52    }
     53}
     54
    3055export class OcrOptions
    3156{
     
    4974        /** @type {String} The URL to which query POST requests should be made. */
    5075        if (process.env.NODE_ENV !== "production") {
    51             this.queryUrl = "//localhost:8383/gs3-atea-ocr/tesseract";
     76            this.queryUrl = "//localhost:8383/gs3-atea-ocr/";
    5277        }
    5378        else {
     
    5681    }
    5782
    58     // TODO: Needs to allow blobs, and take file name
    5983    /**
    6084     * Makes an OCR request.
    6185     * @param {{image: Blob, fileName: String, options: OcrOptions}[]} images The image set to perform OCR on.
    62      * @returns {Promise<{key: String, fileName: String, text: String}[]>} A JSON list of the recognised text.
     86     * @returns {Promise<OcrResult[]>} A JSON list of the recognised text.
    6387     */
    6488    async run(images)
    6589    {
    66         const queryUrl = this.queryUrl;
     90        const queryUrl = this.queryUrl + "tesseract";
    6791
    6892        try
     
    92116            if (!response.ok)
    93117            {
    94                 log(`OCR failed  with status ${response.status} and message ${response.statusText}`, "error");
     118                log(`OCR failed with status ${response.status} and message ${response.statusText}`, "error");
    95119                throw new OcrError(response.statusText, null, response.status);
    96120            }
     
    104128        }
    105129    }
     130
     131    /**
     132     * Gets a thresholded image.
     133     * @param {String} key The image key
     134     */
     135    async getThresholdedImage(key)
     136    {
     137        const queryUrl = this.queryUrl + `image?key=${key}`;
     138
     139        try
     140        {
     141            const response = await fetch(queryUrl);
     142
     143            if (!response.ok)
     144            {
     145                log(`Thresholded image retrieval failed with status ${response.status} and message ${response.statusText}`, "error");
     146                throw new OcrError("Thresholded image retrieval failed: " + response.statusText, null, response.status);
     147            }
     148
     149            return await response.blob(); // TODO: Should this be arraybuffer?
     150        }
     151        catch (e)
     152        {
     153            log(`Thresholded image retrieval failed with reason ${e}`, "error");
     154            throw new OcrError("Thresholded image retrieval failed", null, null)
     155        }
     156    }
    106157}
Note: See TracChangeset for help on using the changeset viewer.