I’m trying to convert cv mat to ImageData object, but I get this error exception:
failed to construct 'ImageData': The input data length is not equal to (4 * width * height)
But that error appears only after converting the cv mat to a different color space, I use the code below to adjust image saturation:
var request = e.data;
var imgData = request.imgData;
var value = request.value;
let src = cv.matFromImageData(imgData);
let hsv = new cv.Mat();
let hsvCopy = new cv.Mat();
cv.cvtColor(src,hsv, cv.COLOR_BGR2HSV);
//create a clone of the hsv image to work on
hsvCopy = hsv.clone();
let channels = new cv.MatVector();
cv.split(hsvCopy, channels);
let hue = channels.get(0);
let saturation = channels.get(1);
let val = channels.get(2);
for (var y = 0; y < saturation.rows; y++)
{
for (var x = 0; x < saturation.cols; x++)
{
saturation.ucharPtr(y,x)[0] = value;
}
}
cv.merge(channels, hsvCopy);
cv.cvtColor(hsvCopy, hsvCopy, cv.COLOR_HSV2BGR);
imgData = new ImageData( new Uint8ClampedArray( hsvCopy.data ), hsvCopy.cols, hsvCopy.rows );
postMessage({
imgData: imgData
});
src.delete();
hsv.delete();
hsvCopy.delete();
there are numpy-like libraries for javascript. I found numjs and tensorflow.js (which has also got a numpy-like interface). that ought to be the basis for OpenCV.js… I wonder if the GSoC person that made OpenCV.js didn’t know, or the libraries didn’t exist yet, or it was too complicated, or not deemed appropriate to depend on external libraries.
as long as you want to set the saturation to a fixed value, you can replace the split / merge and the for loops with a plain setTo()
let src = cv.matFromImageData(imgData);
let hsv = new cv.Mat();
cv.cvtColor(src,hsv, cv.COLOR_RGB2HSV);
// empty mask
let mask = new cv.Mat(hsv.size(), hsv.type());
// set 2nd channel to "on"
mask.setTo([0,255,0,0]);
// set (constant) saturation channel, using the mask
hsv.setTo([0,value,0,0], mask)
let rgb = new cv.Mat();
cv.cvtColor(hsv, rgb, cv.COLOR_HSV2RGB);
cv.cvtColor(rgb, rgb, cv.COLOR_RGB2RGBA);
imgData = new ImageData( new Uint8ClampedArray( rgb.data ), rgb.cols, rgb.rows );
I thought about this after I looked into the opencv.js file precisely in “imshow” function,
I found that input mat parameter is being converted into a 4 channel using cv.cvtColor(hsvCopy, hsvCopy, cv.COLOR_RGB2RGBA);, which is very obvious.