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.
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