openCV Js加法和减法产生意外结果

hwamh0ep  于 2022-11-15  发布在  其他
关注(0)|答案(1)|浏览(159)

我使用gaussianBlur来获得图像的高通,但是cv.subtract()函数似乎不能逐个像素地减去两个图像。我通过首先从输入图像中减去模糊图像,然后再将模糊图像加到结果中来确认这一点。这样做的话,输出应该与输入图像相同,但它是不同的。

  1. img=src
  2. cv.GaussianBlur(img, blur, new cv.Size(21, 21), 0,0,cv.BORDER_DEFAULT)
  3. let x = new cv.Mat()
  4. let y = new cv.Mat()
  5. cv.subtract(img,blur,x)
  6. cv.add(x,blur,y)

以下是参考input imageblurred imageoutput image的图像

r7xajy2e

r7xajy2e1#

如前所述,cv.addcv.subtract函数将uint8求和/相减元素裁剪到范围[0,255]。
解决方案是将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元素被剪切到范围[-32768,32767],我们没有接近这些范围限制。
计算:int16(200) + int16(100)-int16(100),结果200(因为int 16(200)+int 16(100)= int 16(300)。不会发生剪切...
使用convertTo成员函数执行从uint8int16的转换:

  1. img.convertTo(img2, cv.CV_16S);
  2. blur.convertTo(blur2, cv.CV_16S);

然后将cv.subtractcv.add套用至int16元素:

  1. cv.subtract(img2, blur2, x)
  2. cv.add(x, blur2, y)

最后,我们可以将结果转换回uint8类型:

  1. y.convertTo(out, cv.CV_8U);

下面是一个应用上述过程并验证out = img的示例:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Hello OpenCV.js</title>
  6. </head>
  7. <body>
  8. <p id="status">OpenCV.js is loading...</p>
  9. <div>
  10. <div class="inputoutput">
  11. <img id="imageSrc" alt="No Image" />
  12. <div class="caption">imageSrc <input type="file" id="fileInput" name="file" /></div>
  13. </div>
  14. <div class="inputoutput">
  15. <canvas id="canvasOutput" ></canvas>
  16. <div class="caption">canvasOutput</div>
  17. </div>
  18. </div>
  19. <script async src="opencv.js" type="text/javascript"></script>
  20. <script type="text/javascript">
  21. let imgElement = document.getElementById('imageSrc');
  22. let inputElement = document.getElementById('fileInput');
  23. inputElement.addEventListener('change', (e) => {
  24. imgElement.src = URL.createObjectURL(e.target.files[0]);
  25. }, false);
  26. //read image
  27. imgElement.onload = function () {
  28. let img = cv.imread(imgElement);
  29. let blur = new cv.Mat();
  30. let x = new cv.Mat();
  31. let y = new cv.Mat();
  32. let img2 = new cv.Mat();
  33. let blur2 = new cv.Mat();
  34. let out = new cv.Mat();
  35. cv.GaussianBlur(img, blur, new cv.Size(21, 21), 0, 0, cv.BORDER_DEFAULT);
  36. img.convertTo(img2, cv.CV_16S); //Convert img from type Uint8Array to type Int16Array
  37. blur.convertTo(blur2, cv.CV_16S); //Convert blur from type Uint8Array to type Int16Array
  38. cv.subtract(img2, blur2, x) //Subtract applies Int16 elements (instead of Uint8 elements).
  39. cv.add(x, blur2, y) //Add applies Int16 elements (instead of Uint8 elements).
  40. y.convertTo(out, cv.CV_8U); //Convert y from type Int16Array to type Uint8Array (out is used as input for imshow).
  41. cv.imshow('canvasOutput', out);
  42. let d = new cv.Mat();
  43. cv.absdiff(out, img, d);
  44. //Compute the sum of absolute difference (for testing)
  45. let sum_abs_dif = 0
  46. for (row = 0; row < d.rows; row++) {
  47. for (col = 0; col < d.cols; col++) {
  48. sum_abs_dif += d.ucharPtr(row, col)[0] + d.ucharPtr(row, col)[1] + d.ucharPtr(row, col)[2];
  49. //d.ucharPtr(row, col)[3] = 255; //Set the alpha (transparency) channel to 255 for testing.
  50. }
  51. }
  52. console.log(sum_abs_dif) //Prints 0
  53. img.delete();
  54. blur.delete();
  55. x.delete();
  56. y.delete();
  57. img2.delete();
  58. blur2.delete();
  59. out.delete();
  60. d.delete();
  61. };
  62. //check openCV
  63. var Module = {
  64. // https://emscripten.org/docs/api_reference/module.html#Module.onRuntimeInitialized
  65. onRuntimeInitialized() {
  66. document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
  67. }
  68. };
  69. </script>
  70. </body>
  71. </html>
展开查看全部

相关问题