我使用gaussianBlur来获得图像的高通量,但似乎cv.substract((函数不会逐个像素地减去两个图像。我通过首先从输入图像中减去模糊图像,然后将模糊图像再次添加到结果中来证实这一点。这样做时,输出应该与输入图像相同,但不同。
img=src
cv.GaussianBlur(img, blur, new cv.Size(21, 21), 0,0,cv.BORDER_DEFAULT)
let x = new cv.Mat()
let y = new cv.Mat()
cv.subtract(img,blur,x)
cv.add(x,blur,y)
以下是参考输入图像、模糊图像、输出图像的图像
如前所述,cv.add
和cv.subtract
函数将uint8
求和/相减元素剪裁到范围[0255]
解决方案是将mat
数据类型从uint8
转换为更大的数据类型int16
。
剪切(伪代码(示例:cv.add(uint8(200), uint8(100))
等于uint8(255)
(而不是300(cv.subtract(uint8(10), uint8(20))
等于uint8(0)
(而不是-10(。
这意味着计算:uint8(200)
+uint8(100)
-uint8(100)
,结果是155
(而不是返回到原始值200(。
解决方案是将mat
数据类型从uint8
转换为更大的数据类型int16
int16
元素被剪裁到范围[-3276832767],我们还没有接近这些范围限制。
计算:int16(200)
+int16(100)
-int16(100)
,结果200
(因为int16(200(+int16(100(=int16(300(。没有剪辑。。。
使用convertTo成员函数执行从uint8
到int16
的转换:
img.convertTo(img2, cv.CV_16S);
blur.convertTo(blur2, cv.CV_16S);
然后将cv.subtract
和cv.add
应用于int16
元素:
cv.subtract(img2, blur2, x)
cv.add(x, blur2, y)
最后,我们可以将结果转换回uint8
类型:
y.convertTo(out, cv.CV_8U);
以下是应用上述程序的示例,并验证out
=img
:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello OpenCV.js</title>
</head>
<body>
<p id="status">OpenCV.js is loading...</p>
<div>
<div class="inputoutput">
<img id="imageSrc" alt="No Image" />
<div class="caption">imageSrc <input type="file" id="fileInput" name="file" /></div>
</div>
<div class="inputoutput">
<canvas id="canvasOutput" ></canvas>
<div class="caption">canvasOutput</div>
</div>
</div>
<script async src="opencv.js" type="text/javascript"></script>
<script type="text/javascript">
let imgElement = document.getElementById('imageSrc');
let inputElement = document.getElementById('fileInput');
inputElement.addEventListener('change', (e) => {
imgElement.src = URL.createObjectURL(e.target.files[0]);
}, false);
//read image
imgElement.onload = function () {
let img = cv.imread(imgElement);
let blur = new cv.Mat();
let x = new cv.Mat();
let y = new cv.Mat();
let img2 = new cv.Mat();
let blur2 = new cv.Mat();
let out = new cv.Mat();
cv.GaussianBlur(img, blur, new cv.Size(21, 21), 0, 0, cv.BORDER_DEFAULT);
img.convertTo(img2, cv.CV_16S); //Convert img from type Uint8Array to type Int16Array
blur.convertTo(blur2, cv.CV_16S); //Convert blur from type Uint8Array to type Int16Array
cv.subtract(img2, blur2, x) //Subtract applies Int16 elements (instead of Uint8 elements).
cv.add(x, blur2, y) //Add applies Int16 elements (instead of Uint8 elements).
y.convertTo(out, cv.CV_8U); //Convert y from type Int16Array to type Uint8Array (out is used as input for imshow).
cv.imshow('canvasOutput', out);
let d = new cv.Mat();
cv.absdiff(out, img, d);
//Compute the sum of absolute difference (for testing)
let sum_abs_dif = 0
for (row = 0; row < d.rows; row++) {
for (col = 0; col < d.cols; col++) {
sum_abs_dif += d.ucharPtr(row, col)[0] + d.ucharPtr(row, col)[1] + d.ucharPtr(row, col)[2];
//d.ucharPtr(row, col)[3] = 255; //Set the alpha (transparency) channel to 255 for testing.
}
}
console.log(sum_abs_dif) //Prints 0
img.delete();
blur.delete();
x.delete();
y.delete();
img2.delete();
blur2.delete();
out.delete();
d.delete();
};
//check openCV
var Module = {
// https://emscripten.org/docs/api_reference/module.html#Module.onRuntimeInitialized
onRuntimeInitialized() {
document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
}
};
</script>
</body>
</html>