diff --git a/README.md b/README.md index 21824e8..ef9ffa4 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ const translations = { 'sc-modal__error-title': "Une erreur est survenue", 'sc-modal__error-button--restart': "Recommencer", 'sc-modal__error-button--quit': "Quitter", + 'sc-modal__video-message-too-white': "Image trop claire", }; diff --git a/src/SlightCapture/image.js b/src/SlightCapture/image.js index 6f9792d..51431df 100644 --- a/src/SlightCapture/image.js +++ b/src/SlightCapture/image.js @@ -117,6 +117,9 @@ export const loadImageAsync = (cv) => (url, color =null ) => { export const cropImage = (cv) => (img, xmin, ymin, witdh, height) => { let rect = new cv.Rect(xmin, ymin, witdh, height); - return img.roi(rect); + const imageNoContiuous = img.roi(rect); + const image = imageNoContiuous.clone(); + imageNoContiuous.delete(); + return image } diff --git a/src/SlightCapture/templateMatching.js b/src/SlightCapture/templateMatching.js index 412b50e..676bd38 100644 --- a/src/SlightCapture/templateMatching.js +++ b/src/SlightCapture/templateMatching.js @@ -1,26 +1,36 @@ -import {imageResize} from "./image.js"; +import {cropImage, imageResize} from "./image.js"; -export const autoAdjustBrightness = (cv) => (image, minimumBrightness=0.8, minimumRatio = 0, maximumRatio = 100) => { +export const autoAdjustBrightness = (cv) => (image, minimumBrightness=0.8, minimumRatio = 0, maximumRatio = 100, template=null) => { let brightness = 0; const src = image; - let cols = src.cols; - if (src.isContinuous()) { - let channels = src.channels(); - for (let row = 0; row < src.rows; row++) { + + + if(template == null){ + template = image; + } + + let cols = template.cols; + let rows = template.rows; + + if(template.isContinuous()) { + let channels = template.channels(); + let data = template.data; + for (let row = 0; row < rows; row++) { for (let col = 0; col < cols; col++) { - let R = src.data[row * cols * channels + col * channels]; - let G = src.data[row * cols * channels + col * channels + 1]; - let B = src.data[row * cols * channels + col * channels + 2]; - brightness += R + G + B; + let R = data[row * cols * channels + col * channels]; + let G = data[row * cols * channels + col * channels + 1]; + let B = data[row * cols * channels + col * channels + 2]; + brightness += R + G + B; } } } - const ratio = ((brightness /3) / (255 * cols * src.rows)) / minimumBrightness; + const ratio = ((brightness /3) / (255 * cols * rows)) / minimumBrightness; if(ratio < maximumRatio && ratio > minimumRatio) { let alpha = 1 / ratio; // # Brightness control let beta = 0; // # Contrast control cv.convertScaleAbs(image, image, alpha, beta) - return {image, ratio: alpha}; + console.log("Brightness adjusted: " + alpha); + return { image, ratio: alpha }; } return { image, ratio: 0 }; } @@ -33,7 +43,15 @@ export const findMatch = (cv) => (template, image, isDrawRectangle = true) => { let anchor = new cv.Point(-1, -1); cv.blur(image, image, ksize, anchor, cv.BORDER_DEFAULT) - const autoAdjustBrightnessResult = autoAdjustBrightness(cv)(image); + let templateWidth = template.cols; + let templateHeight = template.rows; + let imageWidth = image.cols; + let imageHeight = image.rows; + const point1RectangleToDetect = new cv.Point(Math.round((imageWidth - templateWidth) / 2), Math.round((imageHeight - templateHeight) / 2)); + const point2RectangleToDetect = new cv.Point(Math.round((imageWidth - templateWidth) / 2) + templateWidth, Math.round((imageHeight - templateHeight) / 2) + templateHeight); + const croppedImage = cropImage(cv)(image.clone(), point1RectangleToDetect.x, point1RectangleToDetect.y, templateWidth, templateHeight); + + const autoAdjustBrightnessResult = autoAdjustBrightness(cv)(image, 0.8, 0,100, croppedImage); image = autoAdjustBrightnessResult.image; cv.matchTemplate(image, template, destination, cv.TM_CCORR_NORMED, mask); let result = cv.minMaxLoc(destination, mask); @@ -43,14 +61,11 @@ export const findMatch = (cv) => (template, image, isDrawRectangle = true) => { let maxPointX = point1DetectedRectangle.x; let maxPointY = point1DetectedRectangle.y; - let templateWidth = template.cols; - let templateHeight = template.rows; + let point2DetectedRectangle = new cv.Point(maxPointX + templateWidth, maxPointY + templateHeight); - let imageWidth = image.cols; - let imageHeight = image.rows; - const point1RectangleToDetect = new cv.Point(Math.round((imageWidth - templateWidth) / 2), Math.round((imageHeight - templateHeight) / 2)); - const point2RectangleToDetect = new cv.Point(Math.round((imageWidth - templateWidth) / 2) + templateWidth, Math.round((imageHeight - templateHeight) / 2) + templateHeight); + + if(isDrawRectangle) { let colorBlue = new cv.Scalar(200, 255, 100, 255); cv.rectangle(image, point1RectangleToDetect, point2RectangleToDetect, colorBlue, 1, cv.LINE_8, 0); diff --git a/src/SlightCapture/video.js b/src/SlightCapture/video.js index de13b90..556c1b2 100644 --- a/src/SlightCapture/video.js +++ b/src/SlightCapture/video.js @@ -83,6 +83,7 @@ const texts = { 'sc-modal__error-title': "Une erreur est survenue", 'sc-modal__error-button--restart': "Recommencer", 'sc-modal__error-button--quit': "Quitter", + 'sc-modal__video-message-too-white': "Image trop claire", }; export const loadVideoAsync = (name) => (cv=null) => async (file, @@ -318,13 +319,22 @@ const captureAsync = (cv) => async (name, beginMatch = Date.now(); } - if(autoAdjustBrightnessRatio > 1.9){ + if(autoAdjustBrightnessRatio > 2){ const size = new cv.Size(300, -280); const font = cv.FONT_HERSHEY_SIMPLEX; const fontScale = imageSourceClone.cols > 2000 ? 8 : 4; const thickness = 10; - let colorRed = new cv.Scalar(200, 200, 0, 100); - cv.putText(imageSourceClone, translations['sc-modal__video-message-too-dark'], new cv.Point(Math.round(size.width * 0.12), Math.round(imageSourceClone.rows *0.12)), font, fontScale, colorRed, thickness, cv.LINE_AA); + let colorYellow = new cv.Scalar(200, 200, 0, 100); + cv.putText(imageSourceClone, translations['sc-modal__video-message-too-dark'], new cv.Point(Math.round(size.width * 0.12), Math.round(imageSourceClone.rows *0.12)), font, fontScale, colorYellow, thickness, cv.LINE_AA); + } + + if(autoAdjustBrightnessRatio < 1){ + const size = new cv.Size(300, -280); + const font = cv.FONT_HERSHEY_SIMPLEX; + const fontScale = imageSourceClone.cols > 2000 ? 8 : 4; + const thickness = 10; + let colorWhite = new cv.Scalar(0, 0, 0, 0); + cv.putText(imageSourceClone, translations['sc-modal__video-message-too-white'], new cv.Point(Math.round(size.width * 0.12), Math.round(imageSourceClone.rows *0.12)), font, fontScale, colorWhite, thickness, cv.LINE_AA); } if (counterTime > 5) { @@ -402,11 +412,12 @@ const captureAsync = (cv) => async (name, } if (imageCv) { + cv.imshow(outputCanvas, imageCv) imageCv.delete(); } if (imageSourceClone) { - cv.imshow(outputCanvas, imageSourceClone) + // cv.imshow(outputCanvas, imageSourceClone) imageSourceClone.delete(); } return src; diff --git a/src/SlightCapture/zoning.js b/src/SlightCapture/zoning.js index 4a6e321..11e478a 100644 --- a/src/SlightCapture/zoning.js +++ b/src/SlightCapture/zoning.js @@ -73,15 +73,15 @@ export const zoneAsync = (cv) => async (sceneUrl, imgDescription, goodMatchSizeT imgCv= sceneUrl; } let imgCvClone = imgCv.clone(); - const autoAdjustBrightnessResult = autoAdjustBrightness(cv)(imgCvClone, 0.5, 10); - imgCvClone = autoAdjustBrightnessResult.image; const marge = Math.round((imgDescription.img.rows+ imgDescription.img.cols) /2 * 0.1); - const point1 = new cv.Point(Math.max(0, Math.round(targetPoints.x1 * imgCvClone.cols) - marge), Math.max(0, Math.round(targetPoints.y1 * imgCvClone.rows) - marge)); const point2 = new cv.Point(Math.min(imgCvClone.cols, Math.round(targetPoints.x2 * imgCvClone.cols) + marge), Math.min( imgCvClone.rows, Math.round(targetPoints.y2 * imgCvClone.rows) + marge)); let imgCvCropped = cropImage(cv)(imgCvClone, point1.x, point1.y, point2.x - point1.x, point2.y - point1.y); - imgCvClone.delete(); + + const autoAdjustBrightnessResult = autoAdjustBrightness(cv)(imgCvCropped, 0.6, 0.5, 50); + imgCvCropped = autoAdjustBrightnessResult.image; + let cropRatio = imgCv.cols / imgCvCropped.cols ; const { image: imgResized, ratio} = imageResize(cv)(imgCvCropped, 1600 * cropRatio); const result = computeAndComputeHomographyRectangle(cv)(imgDescription, imgResized, goodMatchSizeThreshold); @@ -135,16 +135,16 @@ export const zoneAsync = (cv) => async (sceneUrl, imgDescription, goodMatchSizeT deleteClean(); - const finalImage = croppedContoursBase64[0]; + const finalImage = croppedContoursBase64.length > 0 ? croppedContoursBase64[0] : null; - /*if(finalImage.isValid()){ + if(!finalImage || !finalImage.isContinuous()){ return { expectedOutput: [], goodMatchSize: 0, finalImage: imgCvCropped, outputInfo: null }; - }*/ + } imgCvCropped.delete(); return {expectedOutput, goodMatchSize: result.goodMatchSize, finalImage, outputInfo};