知识点

  1. 像素算术操作
  • 加 add
  • 减 subtract
  • 乘 multiply
  • 除 divide

  1. 参与运算的图像的数据类型、通道数目、大小必须相同

  2. 读取图像的 imread() 函数有第二个参数,其默认值是 IMREAD_COLOR,即将加载的图像总是转换为彩色图像。转换后图像的类型是 CV_8UC3。

  3. C++ 使用 saturate_cast 防止数据溢出

    C++代码

    ```cpp

    include

    include

using namespace std; using namespace cv;

void day05() {

  1. Mat src1 = imread("E:\\_Image\\OpenCVTest\\girl.jpg");
  2. if (src1.empty()) {
  3. cout << "could not load image1.." << endl;
  4. return;
  5. }
  6. // 第二个参数默认值是 IMREAD_COLOR
  7. // 即将加载的图像总是转换为彩色图像。转换后图像的类型是 CV_8UC3。
  8. Mat src2 = imread("E:\\_Image\\OpenCVTest\\girl_gray.jpg");
  9. if (src2.empty()) {
  10. cout << "could not load image2.." << endl;
  11. return;
  12. }
  13. if (src1.channels() != src2.channels()) {
  14. cout << "chennels is not equal!" << endl;
  15. return;
  16. }
  17. imshow("input1", src1);
  18. imshow("input2", src2);
  19. // 自己实现的 add 算法
  20. int height = src1.rows;
  21. int width = src1.cols;
  22. int b1 = 0, g1 = 0, r1 = 0;
  23. int b2 = 0, g2 = 0, r2 = 0;
  24. int b = 0, g = 0, r = 0;
  25. Mat result = Mat::zeros(src1.size(), src1.type());
  26. for (int row = 0; row < height; row++) {
  27. for (int col = 0; col < width; col++) {
  28. b1 = src1.at<Vec3b>(row, col)[0];
  29. g1 = src1.at<Vec3b>(row, col)[1];
  30. r1 = src1.at<Vec3b>(row, col)[2];
  31. b2 = src2.at<Vec3b>(row, col)[0];
  32. g2 = src2.at<Vec3b>(row, col)[1];
  33. r2 = src2.at<Vec3b>(row, col)[2];
  34. // saturate_cast 防止数据溢出
  35. result.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b1 + b2);
  36. result.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g1 + g2);
  37. result.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r1 + r2);
  38. }
  39. }
  40. imshow("output", result);
  41. // 直接调用 API
  42. Mat add_result = Mat::zeros(src1.size(), src1.type());
  43. add(src1, src2, add_result);
  44. imshow("add_result", add_result);
  45. Mat sub_result = Mat::zeros(src1.size(), src1.type());
  46. subtract(src1, src2, sub_result);
  47. imshow("sub_result", sub_result);
  48. Mat mul_result = Mat::zeros(src1.size(), src1.type());
  49. multiply(src1, src2, mul_result);
  50. imshow("mul_result", mul_result);
  51. Mat div_result = Mat::zeros(src1.size(), src1.type());
  52. divide(src1, src2, div_result);
  53. imshow("div_result", div_result);
  54. waitKey(0);

}


<a name="KZEax"></a>
## Python代码
```python
import cv2 as cv
import numpy as np

# 查看版本
print(cv.__version__)

# 读取图像
src1 = cv.imread("E:/_Image/OpenCVTest/girl.jpg")
src2 = cv.imread("E:/_Image/OpenCVTest/girl_gray.jpg")

# 展示
cv.imshow("input1", src1)
cv.imshow("input2", src2)

# 获取属性
h, w, ch = src1.shape
print("h , w, ch", h, w, ch)

# 调用 API 算数操作
add_result = np.zeros(src1.shape, src1.dtype)
cv.add(src1, src2, add_result)
cv.imshow("add_result", add_result)

sub_result = np.zeros(src1.shape, src1.dtype)
cv.subtract(src1, src2, sub_result)
cv.imshow("sub_result", sub_result)

mul_result = np.zeros(src1.shape, src1.dtype)
cv.multiply(src1, src2, mul_result)
cv.imshow("mul_result", mul_result)

div_result = np.zeros(src1.shape, src1.dtype)
cv.divide(src1, src2, div_result)
cv.imshow("div_result", div_result)

# 等待键盘输入 释放内存
cv.waitKey(0)
cv.destroyAllWindows()

Javascript代码

<template>
  <div>
    <p>图像像素算数操作</p>
    <p id="status">OpenCV.js is loading...</p>
    <div class="inputoutput">
      <img id="imageSrc1" src="imgs/girl.jpg" />
      <img id="imageSrc2" src="imgs/girl_gray.jpg" />
    </div>
    <div class="inputoutput">
      <canvas id="canvasOutput"></canvas>
      <div class="caption">canvasOutput</div>
    </div>
  </div>
</template>

<script>
export default {
  name: "day05",
  mounted() {
    this.init();
  },
  methods: {
    init() {
      setTimeout(() => {
        if (window.cv) {
          this.onOpenCvReady(window.cv);
        } else {
          this.init();
        }
      }, 500);
    },
    onOpenCvReady(cv) {
      document.getElementById("status").innerHTML = "OpenCV.js is ready.";

      let src1 = cv.imread("imageSrc1");
      let src2 = cv.imread("imageSrc2");
      let dst = new cv.Mat();

      // 官方文档链接
      // https://docs.opencv.org/4.5.0/dd/d4d/tutorial_js_image_arithmetics.html

      // 加法
      //   cv.add(src1, src2, dst);

      // 减法
      // Note that when used with RGBA images, the alpha channel is also subtracted.
      cv.cvtColor(src1, src1, cv.COLOR_RGBA2RGB);
      cv.cvtColor(src2, src2, cv.COLOR_RGBA2RGB);
      cv.subtract(src1, src2, dst);

      // 乘法
      //   cv.multiply(src1, src2, dst);

      // 除法
      //   cv.divide(src1, src2, dst);

      cv.imshow("canvasOutput", dst);

      src1.delete();
      src2.delete();
      dst.delete();
    },
  },
};
</script>

<style lang="scss" scoped>
</style>

image.png
image.png
image.png