From f0756428813ca42408c64ced735c3ed42ca566cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 03:25:04 +0000 Subject: [PATCH 1/4] Initial plan From 0f69dc0cd2e49b0749b90aa3485ff874b5702d98 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 03:37:44 +0000 Subject: [PATCH 2/4] Add QRCodeDetector TypeScript definitions and tests Co-authored-by: ttt43ttt <132509+ttt43ttt@users.noreply.github.com> --- src/types/opencv/QRCodeDetector.ts | 111 +++++++++++++++++++ src/types/opencv/QRCodeDetectorAruco.ts | 139 ++++++++++++++++++++++++ src/types/opencv/objdetect.ts | 3 + test/QRCodeDetector.test.ts | 121 +++++++++++++++++++++ test/qr-types-test.ts | 29 +++++ 5 files changed, 403 insertions(+) create mode 100644 src/types/opencv/QRCodeDetector.ts create mode 100644 src/types/opencv/QRCodeDetectorAruco.ts create mode 100644 test/QRCodeDetector.test.ts create mode 100644 test/qr-types-test.ts diff --git a/src/types/opencv/QRCodeDetector.ts b/src/types/opencv/QRCodeDetector.ts new file mode 100644 index 0000000..a71f9d7 --- /dev/null +++ b/src/types/opencv/QRCodeDetector.ts @@ -0,0 +1,111 @@ +import type { + bool, + InputArray, + InputOutputArray, + OutputArray, + OutputArrayOfArrays, + Point2f, +} from "./_types"; + +/** + * QR Code detection and decoding class. + * + * This class implements QR code detection and decoding functionality. + * It can detect QR codes in an image and decode their content. + * + * Source: + * [opencv2/objdetect.hpp](https://github.com/opencv/opencv/tree/master/modules/objdetect/include/opencv2/objdetect.hpp). + */ +export declare class QRCodeDetector { + /** + * QRCodeDetector constructor + */ + public constructor(); + + /** + * Detects QR code in image and returns the quadrangle containing the code. + * + * @param img grayscale or color (BGR) image containing (or not) QR code. + * @param points Output vector of vertices of the minimum-area quadrangle containing the code. + */ + public detect(img: InputArray, points: OutputArray): bool; + + /** + * Decodes QR code in image once it's found by the detect() method. + * + * @param img grayscale or color (BGR) image containing QR code. + * @param points Quadrangle vertices found by detect() method (or some other algorithm). + * @param straight_qrcode The optional output image containing rectified and binarized QR code + */ + public decode( + img: InputArray, + points: InputArray, + straight_qrcode?: OutputArray + ): String; + + /** + * Both detects and decodes QR code + * + * @param img grayscale or color (BGR) image containing QR code. + * @param points optional output array of vertices of the found QR code quadrangle. Will be empty if not found. + * @param straight_qrcode The optional output image containing rectified and binarized QR code + */ + public detectAndDecode( + img: InputArray, + points?: OutputArray, + straight_qrcode?: OutputArray + ): String; + + /** + * Detects QR codes in image and returns the vector of the quadrangles containing the codes. + * + * @param img grayscale or color (BGR) image containing (or not) QR codes. + * @param points Output vector of vector of vertices of the minimum-area quadrangle containing the codes. + */ + public detectMulti(img: InputArray, points: OutputArrayOfArrays): bool; + + /** + * Decodes QR codes in image once it's found by the detectMulti() method. + * + * @param img grayscale or color (BGR) image containing QR codes. + * @param points vector of Quadrangle vertices found by detectMulti() method (or some other algorithm). + * @param decoded_info UTF8-encoded output vector of String or empty vector of String if the codes cannot be decoded. + * @param straight_qrcode The optional output vector of images containing rectified and binarized QR codes + */ + public decodeMulti( + img: InputArray, + points: InputArray, + decoded_info: any, + straight_qrcode?: OutputArrayOfArrays + ): bool; + + /** + * Both detects and decodes QR codes + * + * @param img grayscale or color (BGR) image containing QR codes. + * @param decoded_info UTF8-encoded output vector of String or empty vector of String if the codes cannot be decoded. + * @param points optional output vector of vertices of the found QR code quadrangles. Will be empty if not found. + * @param straight_qrcode The optional output vector of images containing rectified and binarized QR codes + */ + public detectAndDecodeMulti( + img: InputArray, + decoded_info: any, + points?: OutputArrayOfArrays, + straight_qrcode?: OutputArrayOfArrays + ): bool; + + /** + * Aruco-based QR code detector + */ + public setUseAruco(use_aruco: bool): void; + + /** + * Get if Aruco-based QR code detector is used + */ + public getUseAruco(): bool; + + /** + * Releases the object + */ + public delete(): void; +} \ No newline at end of file diff --git a/src/types/opencv/QRCodeDetectorAruco.ts b/src/types/opencv/QRCodeDetectorAruco.ts new file mode 100644 index 0000000..706c4a3 --- /dev/null +++ b/src/types/opencv/QRCodeDetectorAruco.ts @@ -0,0 +1,139 @@ +import type { + bool, + float, + InputArray, + OutputArray, + OutputArrayOfArrays, +} from "./_types"; + +/** + * Parameters for QRCodeDetectorAruco + */ +export declare class QRCodeDetectorAruco_Params { + public minModuleSizeInPyramid: float; + public maxRotation: float; + public maxModuleSizeMismatch: float; + public maxTimingPatternMismatch: float; + public maxPenalties: float; + public maxColorsMismatch: float; + public scaleTimingPatternScore: float; + + public constructor(); + + /** + * Releases the object + */ + public delete(): void; +} + +/** + * QR Code detection and decoding class using Aruco-based detection. + * + * This class implements QR code detection and decoding functionality using + * Aruco marker detection techniques for improved robustness. + * + * Source: + * [opencv2/objdetect.hpp](https://github.com/opencv/opencv/tree/master/modules/objdetect/include/opencv2/objdetect.hpp). + */ +export declare class QRCodeDetectorAruco { + /** + * QRCodeDetectorAruco constructor + */ + public constructor(); + + /** + * QRCodeDetectorAruco constructor with parameters + * + * @param params QRCodeDetectorAruco parameters + */ + public constructor(params: QRCodeDetectorAruco_Params); + + /** + * Detects QR code in image and returns the quadrangle containing the code. + * + * @param img grayscale or color (BGR) image containing (or not) QR code. + * @param points Output vector of vertices of the minimum-area quadrangle containing the code. + */ + public detect(img: InputArray, points: OutputArray): bool; + + /** + * Decodes QR code in image once it's found by the detect() method. + * + * @param img grayscale or color (BGR) image containing QR code. + * @param points Quadrangle vertices found by detect() method (or some other algorithm). + * @param straight_qrcode The optional output image containing rectified and binarized QR code + */ + public decode( + img: InputArray, + points: InputArray, + straight_qrcode?: OutputArray + ): String; + + /** + * Both detects and decodes QR code + * + * @param img grayscale or color (BGR) image containing QR code. + * @param points optional output array of vertices of the found QR code quadrangle. Will be empty if not found. + * @param straight_qrcode The optional output image containing rectified and binarized QR code + */ + public detectAndDecode( + img: InputArray, + points?: OutputArray, + straight_qrcode?: OutputArray + ): String; + + /** + * Detects QR codes in image and returns the vector of the quadrangles containing the codes. + * + * @param img grayscale or color (BGR) image containing (or not) QR codes. + * @param points Output vector of vector of vertices of the minimum-area quadrangle containing the codes. + */ + public detectMulti(img: InputArray, points: OutputArrayOfArrays): bool; + + /** + * Decodes QR codes in image once it's found by the detectMulti() method. + * + * @param img grayscale or color (BGR) image containing QR codes. + * @param points vector of Quadrangle vertices found by detectMulti() method (or some other algorithm). + * @param decoded_info UTF8-encoded output vector of String or empty vector of String if the codes cannot be decoded. + * @param straight_qrcode The optional output vector of images containing rectified and binarized QR codes + */ + public decodeMulti( + img: InputArray, + points: InputArray, + decoded_info: any, + straight_qrcode?: OutputArrayOfArrays + ): bool; + + /** + * Both detects and decodes QR codes + * + * @param img grayscale or color (BGR) image containing QR codes. + * @param decoded_info UTF8-encoded output vector of String or empty vector of String if the codes cannot be decoded. + * @param points optional output vector of vertices of the found QR code quadrangles. Will be empty if not found. + * @param straight_qrcode The optional output vector of images containing rectified and binarized QR codes + */ + public detectAndDecodeMulti( + img: InputArray, + decoded_info: any, + points?: OutputArrayOfArrays, + straight_qrcode?: OutputArrayOfArrays + ): bool; + + /** + * Get detector parameters + */ + public getDetectorParameters(): QRCodeDetectorAruco_Params; + + /** + * Set detector parameters + * + * @param params QRCodeDetectorAruco parameters + */ + public setDetectorParameters(params: QRCodeDetectorAruco_Params): void; + + /** + * Releases the object + */ + public delete(): void; +} \ No newline at end of file diff --git a/src/types/opencv/objdetect.ts b/src/types/opencv/objdetect.ts index 5b8be12..2d870b3 100644 --- a/src/types/opencv/objdetect.ts +++ b/src/types/opencv/objdetect.ts @@ -101,3 +101,6 @@ export declare const CASCADE_SCALE_IMAGE: any; // initializer: = 2 export declare const CASCADE_FIND_BIGGEST_OBJECT: any; // initializer: = 4 export declare const CASCADE_DO_ROUGH_SEARCH: any; // initializer: = 8 + +export { QRCodeDetector } from "./QRCodeDetector"; +export { QRCodeDetectorAruco, QRCodeDetectorAruco_Params } from "./QRCodeDetectorAruco"; diff --git a/test/QRCodeDetector.test.ts b/test/QRCodeDetector.test.ts new file mode 100644 index 0000000..c727b9b --- /dev/null +++ b/test/QRCodeDetector.test.ts @@ -0,0 +1,121 @@ +import { setupOpenCv } from "./cv"; + +beforeAll(async () => { + await setupOpenCv(); +}); + +describe("QRCodeDetector", () => { + it("should be available as a class", () => { + expect(cv.QRCodeDetector).toBeDefined(); + expect(typeof cv.QRCodeDetector).toBe("function"); + }); + + it("should be able to create QRCodeDetector instance", () => { + const detector = new cv.QRCodeDetector(); + expect(detector).toBeDefined(); + expect(detector.constructor.name).toBe("QRCodeDetector"); + }); + + it("should have detect method", () => { + const detector = new cv.QRCodeDetector(); + expect(detector.detect).toBeDefined(); + expect(typeof detector.detect).toBe("function"); + }); + + it("should have decode method", () => { + const detector = new cv.QRCodeDetector(); + expect(detector.decode).toBeDefined(); + expect(typeof detector.decode).toBe("function"); + }); + + it("should have detectAndDecode method", () => { + const detector = new cv.QRCodeDetector(); + expect(detector.detectAndDecode).toBeDefined(); + expect(typeof detector.detectAndDecode).toBe("function"); + }); + + it("should have detectMulti method", () => { + const detector = new cv.QRCodeDetector(); + expect(detector.detectMulti).toBeDefined(); + expect(typeof detector.detectMulti).toBe("function"); + }); + + it("should have decodeMulti method", () => { + const detector = new cv.QRCodeDetector(); + expect(detector.decodeMulti).toBeDefined(); + expect(typeof detector.decodeMulti).toBe("function"); + }); + + it("should have detectAndDecodeMulti method", () => { + const detector = new cv.QRCodeDetector(); + expect(detector.detectAndDecodeMulti).toBeDefined(); + expect(typeof detector.detectAndDecodeMulti).toBe("function"); + }); + + it("should be able to clean up detector", () => { + const detector = new cv.QRCodeDetector(); + // Just verify we can call delete without errors + expect(() => detector.delete()).not.toThrow(); + }); +}); + +describe("QRCodeDetectorAruco", () => { + it("should be available as a class", () => { + expect(cv.QRCodeDetectorAruco).toBeDefined(); + expect(typeof cv.QRCodeDetectorAruco).toBe("function"); + }); + + it("should be able to create QRCodeDetectorAruco instance", () => { + const detector = new cv.QRCodeDetectorAruco(); + expect(detector).toBeDefined(); + expect(detector.constructor.name).toBe("QRCodeDetectorAruco"); + }); + + it("should have detect method", () => { + const detector = new cv.QRCodeDetectorAruco(); + expect(detector.detect).toBeDefined(); + expect(typeof detector.detect).toBe("function"); + }); + + it("should have decode method", () => { + const detector = new cv.QRCodeDetectorAruco(); + expect(detector.decode).toBeDefined(); + expect(typeof detector.decode).toBe("function"); + }); + + it("should have detectAndDecode method", () => { + const detector = new cv.QRCodeDetectorAruco(); + expect(detector.detectAndDecode).toBeDefined(); + expect(typeof detector.detectAndDecode).toBe("function"); + }); + + it("should be able to clean up detector", () => { + const detector = new cv.QRCodeDetectorAruco(); + // Just verify we can call delete without errors + expect(() => detector.delete()).not.toThrow(); + }); +}); + +describe("QRCodeDetectorAruco_Params", () => { + it("should be available as a class", () => { + expect(cv.QRCodeDetectorAruco_Params).toBeDefined(); + expect(typeof cv.QRCodeDetectorAruco_Params).toBe("function"); + }); + + it("should be able to create QRCodeDetectorAruco_Params instance", () => { + const params = new cv.QRCodeDetectorAruco_Params(); + expect(params).toBeDefined(); + expect(params.constructor.name).toBe("QRCodeDetectorAruco_Params"); + }); + + it("should have expected properties", () => { + const params = new cv.QRCodeDetectorAruco_Params(); + expect(params.minModuleSizeInPyramid).toBeDefined(); + expect(params.maxRotation).toBeDefined(); + expect(params.maxModuleSizeMismatch).toBeDefined(); + expect(params.maxTimingPatternMismatch).toBeDefined(); + expect(params.maxPenalties).toBeDefined(); + expect(params.maxColorsMismatch).toBeDefined(); + expect(params.scaleTimingPatternScore).toBeDefined(); + }); +}); \ No newline at end of file diff --git a/test/qr-types-test.ts b/test/qr-types-test.ts new file mode 100644 index 0000000..5a32773 --- /dev/null +++ b/test/qr-types-test.ts @@ -0,0 +1,29 @@ +// Simple TypeScript compilation test for QRCodeDetector +// This demonstrates that the types are properly exposed + +import { CV } from "../src/types/opencv"; + +// This should compile without errors, demonstrating that: +// 1. QRCodeDetector is available as a type +// 2. QRCodeDetectorAruco is available as a type +// 3. QRCodeDetectorAruco_Params is available as a type +// 4. All methods have proper type signatures + +function demonstrateQRCodeDetectorTypes(cv: CV) { + // TypeScript should provide intellisense and type checking for these: + + const detector = new cv.QRCodeDetector(); + const arucoDetector = new cv.QRCodeDetectorAruco(); + const params = new cv.QRCodeDetectorAruco_Params(); + + // Example method calls that should have proper type checking: + // const detected: boolean = detector.detect(image, points); + // const decoded: string = detector.decode(image, points); + // const result: string = detector.detectAndDecode(image); + + detector.delete(); + arucoDetector.delete(); + params.delete(); +} + +export { demonstrateQRCodeDetectorTypes }; \ No newline at end of file From 81945c0526506f4dd209304ec86a39d9c3c4027a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 03:38:43 +0000 Subject: [PATCH 3/4] Remove temporary test file from project Co-authored-by: ttt43ttt <132509+ttt43ttt@users.noreply.github.com> --- test/qr-types-test.ts | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 test/qr-types-test.ts diff --git a/test/qr-types-test.ts b/test/qr-types-test.ts deleted file mode 100644 index 5a32773..0000000 --- a/test/qr-types-test.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Simple TypeScript compilation test for QRCodeDetector -// This demonstrates that the types are properly exposed - -import { CV } from "../src/types/opencv"; - -// This should compile without errors, demonstrating that: -// 1. QRCodeDetector is available as a type -// 2. QRCodeDetectorAruco is available as a type -// 3. QRCodeDetectorAruco_Params is available as a type -// 4. All methods have proper type signatures - -function demonstrateQRCodeDetectorTypes(cv: CV) { - // TypeScript should provide intellisense and type checking for these: - - const detector = new cv.QRCodeDetector(); - const arucoDetector = new cv.QRCodeDetectorAruco(); - const params = new cv.QRCodeDetectorAruco_Params(); - - // Example method calls that should have proper type checking: - // const detected: boolean = detector.detect(image, points); - // const decoded: string = detector.decode(image, points); - // const result: string = detector.detectAndDecode(image); - - detector.delete(); - arucoDetector.delete(); - params.delete(); -} - -export { demonstrateQRCodeDetectorTypes }; \ No newline at end of file From 3036feffc957acf8276f2198c198cd41206b762d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 5 Sep 2025 04:23:22 +0000 Subject: [PATCH 4/4] Add comprehensive QR code detection tests with real image Co-authored-by: ttt43ttt <132509+ttt43ttt@users.noreply.github.com> --- test/QRCodeDetector.test.ts | 132 ++++++++++++++++++++++++++++++++++++ test/test-qr.png | Bin 0 -> 1793 bytes 2 files changed, 132 insertions(+) create mode 100644 test/test-qr.png diff --git a/test/QRCodeDetector.test.ts b/test/QRCodeDetector.test.ts index c727b9b..76e1453 100644 --- a/test/QRCodeDetector.test.ts +++ b/test/QRCodeDetector.test.ts @@ -1,3 +1,5 @@ +import { Jimp } from "jimp"; +import path from "path"; import { setupOpenCv } from "./cv"; beforeAll(async () => { @@ -57,6 +59,98 @@ describe("QRCodeDetector", () => { // Just verify we can call delete without errors expect(() => detector.delete()).not.toThrow(); }); + + it("should detect and decode QR code from image", async () => { + const detector = new cv.QRCodeDetector(); + + try { + // Load the test QR code image + const jimpSrc = await Jimp.read(path.resolve(__dirname, "test-qr.png")); + const img = cv.matFromImageData(jimpSrc.bitmap); + + // Convert RGBA to BGR as OpenCV expects BGR format + const imgBGR = new cv.Mat(); + cv.cvtColor(img, imgBGR, cv.COLOR_RGBA2BGR); + + // Test detectAndDecode method + const points = new cv.Mat(); + const decodedText = detector.detectAndDecode(imgBGR, points); + + // Verify the decoded text matches what we encoded + expect(decodedText).toBe("Hello OpenCV.js QR Test!"); + + // Verify points were detected (should have 4 corner points) + expect(points.rows).toBeGreaterThan(0); + expect(points.cols).toBeGreaterThan(0); + + // Clean up + img.delete(); + imgBGR.delete(); + points.delete(); + } finally { + detector.delete(); + } + }); + + it("should detect QR code corners using detect method", async () => { + const detector = new cv.QRCodeDetector(); + + try { + // Load the test QR code image + const jimpSrc = await Jimp.read(path.resolve(__dirname, "test-qr.png")); + const img = cv.matFromImageData(jimpSrc.bitmap); + + // Convert RGBA to BGR as OpenCV expects BGR format + const imgBGR = new cv.Mat(); + cv.cvtColor(img, imgBGR, cv.COLOR_RGBA2BGR); + + // Test detect method + const points = new cv.Mat(); + const detected = detector.detect(imgBGR, points); + + // Verify QR code was detected + expect(detected).toBe(true); + expect(points.rows).toBeGreaterThan(0); + expect(points.cols).toBeGreaterThan(0); + + // Clean up + img.delete(); + imgBGR.delete(); + points.delete(); + } finally { + detector.delete(); + } + }); + + it("should decode previously detected QR code using decode method", async () => { + const detector = new cv.QRCodeDetector(); + + try { + // Load the test QR code image + const jimpSrc = await Jimp.read(path.resolve(__dirname, "test-qr.png")); + const img = cv.matFromImageData(jimpSrc.bitmap); + + // Convert RGBA to BGR as OpenCV expects BGR format + const imgBGR = new cv.Mat(); + cv.cvtColor(img, imgBGR, cv.COLOR_RGBA2BGR); + + // First detect the QR code + const points = new cv.Mat(); + const detected = detector.detect(imgBGR, points); + expect(detected).toBe(true); + + // Then decode it using the detected points + const decodedText = detector.decode(imgBGR, points); + expect(decodedText).toBe("Hello OpenCV.js QR Test!"); + + // Clean up + img.delete(); + imgBGR.delete(); + points.delete(); + } finally { + detector.delete(); + } + }); }); describe("QRCodeDetectorAruco", () => { @@ -94,6 +188,38 @@ describe("QRCodeDetectorAruco", () => { // Just verify we can call delete without errors expect(() => detector.delete()).not.toThrow(); }); + + it("should detect and decode QR code from image using Aruco detector", async () => { + const detector = new cv.QRCodeDetectorAruco(); + + try { + // Load the test QR code image + const jimpSrc = await Jimp.read(path.resolve(__dirname, "test-qr.png")); + const img = cv.matFromImageData(jimpSrc.bitmap); + + // Convert RGBA to BGR as OpenCV expects BGR format + const imgBGR = new cv.Mat(); + cv.cvtColor(img, imgBGR, cv.COLOR_RGBA2BGR); + + // Test detectAndDecode method + const points = new cv.Mat(); + const decodedText = detector.detectAndDecode(imgBGR, points); + + // Verify the decoded text matches what we encoded + expect(decodedText).toBe("Hello OpenCV.js QR Test!"); + + // Verify points were detected + expect(points.rows).toBeGreaterThan(0); + expect(points.cols).toBeGreaterThan(0); + + // Clean up + img.delete(); + imgBGR.delete(); + points.delete(); + } finally { + detector.delete(); + } + }); }); describe("QRCodeDetectorAruco_Params", () => { @@ -118,4 +244,10 @@ describe("QRCodeDetectorAruco_Params", () => { expect(params.maxColorsMismatch).toBeDefined(); expect(params.scaleTimingPatternScore).toBeDefined(); }); + + it("should be able to clean up params", () => { + const params = new cv.QRCodeDetectorAruco_Params(); + // Just verify we can call delete without errors + expect(() => params.delete()).not.toThrow(); + }); }); \ No newline at end of file diff --git a/test/test-qr.png b/test/test-qr.png new file mode 100644 index 0000000000000000000000000000000000000000..97c9faf64e7b98c91ec49aaf15a895c314583e19 GIT binary patch literal 1793 zcmb7FT}V@582&az(hwR7icyvlHkKw4EhZ`E)HE8Eq8Eou`!Ss!y&9G{O_`+q36?j> z$cz$OC(WNvn3y%}CQDG-(49oAo0y3c8ZC3$`<`iab&g$}9lmq+z2Eab&+|T~`Lr%G zG$bm75E7boLVK1F*#W$^1;LYR#=8c%$+NVnxmRW1qH3oI39{m9@l8Fu>!>^}wbknz zdVew?IPiJRp+)tVwY?;AhwOFJHj<$wi81o)3I(~{L<+TmBsPXbDz^G6+9=~~ql5Nf z-pX;hX-6})exL=VmN42_S7vFKF4eNT%<|AiYg=(+h2D}wJ=u&e9Dc=-Bu5o7Jp*Df`N2c;d&oJ{#;xsHzUZjnq{ahGpc!wth^BOyzsAb}N<5#OBg&E5{ z-@&g!o^iG|0fMrrJ(UpEr^xg1nc;I{e+_bLg!1eyXLplzvTZojxa zqmA{{@4jxjqAXu%qngVA1lo%)v9#m5dY@DU84o8{^n;H=>aH+7(+(B&%+5HvsZ}Yy z71Z&5-Hx_cQ951sv3J1TzQOEp85p{8Jwd!i^c~oQ1e$yQp~A1mW;23DFdz9+UWyQE z