Search code examples
javascriptreactjsxmlopencvartificial-intelligence

what is the correct way to load an xml file into reactjs?


i'm working on a MERN Stack project for the university where users can upload pictures of cars, and i want to use opencv to blur out the license plates, thus i need to use a "haarcascades" file to identify the area. here is the relevant code:

  const handlePhotosChange = async (e) => {
    const { files } = e.target;
    const selectedPhotos = Array.from(files);

    for (const photo of selectedPhotos) {
      const img = new Image();
      img.src = URL.createObjectURL(photo);

      await new Promise((resolve) => {
        img.onload = () => {
          resolve();
        };
      });

      const mat = cv.imread(img);
      const gray = new cv.Mat();
      cv.cvtColor(mat, gray, cv.COLOR_RGBA2GRAY);

      const licensePlateCascade = new cv.CascadeClassifier();
      const cascadeLoaded = licensePlateCascade.load(
        "haarcascade_license_plate_rus_16stages.xml"
      );
      console.log("1");
      if (cascadeLoaded) {
        console.log("2");
        const plates = new cv.RectVector();
        const minSize = new cv.Size(30, 30);
        licensePlateCascade.detectMultiScale(gray, plates, 1.1, 3, 0, minSize);

        for (let i = 0; i < plates.size(); i++) {
          const plate = plates.get(i);
          const plateMat = gray.roi(plate);
          cv.GaussianBlur(plateMat, plateMat, new cv.Size(5, 5), 0);
          plateMat.delete();
        }

        const blurredImg = new Image();
        blurredImg.src = URL.createObjectURL(
          new Blob([cv.imencode(".jpg", mat)], { type: "image/jpeg" })
        );
        const blurredBlob = await fetch(blurredImg.src).then((res) =>
          res.blob()
        );

        selectedPhotos[selectedPhotos.indexOf(photo)] = blurredBlob;

        plates.delete();
      }

      mat.delete();
      gray.delete();
      licensePlateCascade.delete();
    }

    setPhotos(selectedPhotos);
  };

i'm having a problem with this line specifically :

      const cascadeLoaded = licensePlateCascade.load(
        "haarcascade_license_plate_rus_16stages.xml"
      );

the moment the code executes, i get this error in console:

[ERROR:0@5.090] global persistence.cpp:531 open Can't open file: 'haarcascade_license_plate_rus_16stages.xml' in read mode

i tried putting the full path, using the row github link , putting the file in public, and putting the code and files in the backend. nothing worked.

the expected behavior: the file loads with no errors.


Solution

  • thanks to the comment of @Christoph Rackwitz i was able to find a solution

    what you need to do:

    1- get the utils.js from OpenCV's GitHub repo.

    2- in order for it to work properly, you need to add this line to it (use the relative path of opencv.js you are using)

    import * as cv from "../opencv/opencv";
    

    3- import it into the component that you want to used the harrcascade in.

    import Utils from "../assets/utils";
    

    also, make sure to import opencv.js too.

    4- next, you'll need to put the haarcascade file of your choice in /public.

    5- assign it to a variable:

    const xmlURL = "haarcascade_xxxx_license_plate.xml";
    

    6- finely, we'll use createFileFromUrl() from utils.js and load our haarcascade file:

    utils.createFileFromUrl(xmlURL, xmlURL, () => {
         licensePlateCascade.load(xmlURL);
    

    here is the full function for your convenience:

      const handleLicensePlateDetection = async (e) => {
    
    try {
      console.log("Starting license plate detection...");
    
      // Clean up previous resources if necessary
      if (window.src) window.src.delete();
      if (window.gray) window.gray.delete();
      if (window.plates) window.plates.delete();
      if (window.licensePlateCascade) window.licensePlateCascade.delete();
    
      const file = e.target.files[0];
      const reader = new FileReader();
      reader.onload = async () => {
        console.log("Image loaded successfully.");
        const image = new Image();
        image.src = reader.result;
        image.onload = async () => {
          console.log("Converting image to grayscale...");
          const src = cv.imread(image);
          const gray = new cv.Mat();
          cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY, 0);
    
          console.log("Loading Haar Cascade XML file...");
          const licensePlateCascade = new cv.CascadeClassifier();
          const xmlURL = "haarcascade_xxx_license_plate.xml"; // Path to the XML file
          utils.createFileFromUrl(xmlURL, xmlURL, () => {
            try {
              licensePlateCascade.load(xmlURL);
              console.log("Haar Cascade XML file loaded successfully.");
    
              console.log("Detecting license plates...");
              const plates = new cv.RectVector();
              const msize = new cv.Size(0, 0);
              licensePlateCascade.detectMultiScale(
                gray,
                plates,
                1.1,
                3,
                0,
                msize,
                msize
              );
    
              console.log("Applying Gaussian blur to detected plates...");
              for (let i = 0; i < plates.size(); ++i) {
                try {
                  const plate = plates.get(i);
                  const roi = src.roi(plate);
                  cv.GaussianBlur(
                    roi,
                    roi,
                    new cv.Size(23, 23),
                    40,
                    40,
                    cv.BORDER_DEFAULT
                  );
                  roi.delete();
                } catch (error) {
                  console.error(
                    "Error applying Gaussian blur to plate:",
                    error
                  );
                }
              }
    
              console.log("Displaying the result...");
              cv.imshow("canvas", src);
    
              // Clean up
              src.delete();
              gray.delete();
              plates.delete();
              licensePlateCascade.delete();
            } catch (error) {
              console.error("Error loading Haar Cascade XML file:", error);
            }
          });
        };
      };
      reader.readAsDataURL(file);
    } catch (error) {
      console.error("Error initializing license plate detection:", error);
    }
      };
    

    note: i'm new to this "AI" stuff and needed the assistance of an AI, thus i don't understand most of what i just pasted