OpenCV4(10)-图像像素值统计(C++,Python,JS)

目录

环境

知识点

C++代码

Python代码

JS代码

结果展示

返回总目录


环境

  • Python:3.6.5 OpenCV 4.1.2
  • C++:OpenCV 4.1.2
  • JS:OpenCV 4.5.0

环境搭建可参考:B站视频

知识点

像素值统计

- 最小(min)

- 最大(max)

- 均值(mean)

- 标准方差(standard deviation)

相关API

- 最大最小值minMaxLoc

minMaxLoc() 函数要求输入图像必须是 CV_8UC1 类型的,否则会报错。

- 计算均值与标准方差meanStdDev

meanStdDev(Mat src, MatOfDouble mean, MatOfDouble stddev)

- src 表示输入 Mat 图像

- mean 表示计算出各个通道的均值,数组长度与通道数目一致

- stddev 表示计算出各个通道的标准方差,数组长度与通道数目一致

C++代码

#ifndef DAY10
#define DAY10

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

void day10() {

	// 读取一张灰度图像
	Mat src_gray = imread("E:\\_Image\\OpenCVTest\\girl.jpg", IMREAD_GRAYSCALE);
	if (src_gray.empty()) {
		cout << "could not load image.." << endl;
		return;
	}
	imshow("src_gray", src_gray);

	if (src_gray.type() == CV_8UC1) {
		double minVal = 0, maxVal = 0;
		Point minLoc, maxLoc;
		minMaxLoc(src_gray, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
		printf("min: %.2f, max: %.2f\n", minVal, maxVal);
		printf("min loc: (%d, %d)\n", minLoc.x, minLoc.y);
		printf("max loc: (%d, %d)\n", maxLoc.x, maxLoc.y);
	}
	else {
		cout << "not gray image.." << endl;
	}
	
	// 读取一张三通道彩色图像,获得它的均值和方差
	Mat src_color = imread("E:\\_Image\\OpenCVTest\\girl.jpg");
	if (src_color.empty()) {
		cout << "could not load image.." << endl;
		return;
	}
	imshow("src_color", src_color);

	Mat mean, stddev;
	meanStdDev(src_color, mean, stddev);
	printf("blue channel -> mean: %.2f, stddev: %2f\n", mean.at<double>(0, 0), stddev.at<double>(0, 0));
	printf("green channel -> mean: %.2f, stddev: %2f\n", mean.at<double>(1, 0), stddev.at<double>(1, 0));
	printf("red channel -> mean: %.2f, stddev: %2f\n", mean.at<double>(2, 0), stddev.at<double>(2, 0));
	
	// 根据图像的均值将彩色图像转换为二值图像
	for (int row = 0; row < src_color.rows; row++) {
		for (int col = 0; col < src_color.cols; col++) {
			Vec3b bgr = src_color.at<Vec3b>(row, col);
			bgr[0] = bgr[0] < mean.at<double>(0, 0) ? 0 : 255;
			bgr[1] = bgr[1] < mean.at<double>(1, 0) ? 0 : 255;
			bgr[2] = bgr[2] < mean.at<double>(2, 0) ? 0 : 255;
			src_color.at<Vec3b>(row, col) = bgr;
		}
	}
	imshow("binary", src_color);

	waitKey(0);
}

#endif // !DAY10

Python代码

import cv2 as cv
import numpy as np

# 查看版本
print(cv.__version__)

# 读取和显示图像
src = cv.imread("E:/_Image/OpenCVTest/girl.jpg", cv.IMREAD_GRAYSCALE)
cv.imshow("src", src)

# 获取灰度图的极值及位置
mmin, mmax, minLoc, maxLoc = cv.minMaxLoc(src)
print("min: %.2f, max: %.2f" % (mmin, mmax))
print("minLoc: ", minLoc)
print("maxLoc: ", maxLoc)

# 获取灰度图的均值和方差
means, stddev = cv.meanStdDev(src)
print("means: %.2f, stddev: %.2f" % (means, stddev))
src[np.where(src < means)] = 0
src[np.where(src > means)] = 255
cv.imshow("binary", src)

## 彩色图像二值化
src = cv.imread("E:/_Image/OpenCVTest/girl.jpg")
cv.imshow("color", src)
h, w, ch = src.shape
means, stddev = cv.meanStdDev(src)
print("blue channel -> means: %.2f, stddev: %.2f" % (means[0], stddev[0]))
print("green channel -> means: %.2f, stddev: %.2f" % (means[1], stddev[1]))
print("red channel -> means: %.2f, stddev: %.2f" % (means[2], stddev[2]))
print("h, w, ch", h, w, ch)
for row in range(h):
    for col in range(w):
        b, g, r = src[row, col]
        b = 0 if b < means[0] else 255
        g = 0 if g < means[1] else 255
        r = 0 if r < means[2] else 255
        src[row, col] = [b, g, r]
cv.imshow("color_binary", src)

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

JS代码

<template>
  <div>
    <p>图像像素值统计</p>
    <p id="status">OpenCV.js is loading...</p>
    <div class="inputoutput">
      <img id="imageSrc" src="imgs/girl.jpg" />
    </div>
    <div class="inputoutput">
      <canvas id="canvasOutput"></canvas>
      <div class="caption">canvasOutput</div>
    </div>
  </div>
</template>

<script>
export default {
  name: "day10",
  mounted() {
    this.init();
  },
  destoryed() {},
  data() {
    return {
      mats: [],
    };
  },
  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 src = this.createMat(cv, 1, { name: "imageSrc" });

      // 转化到 gray 色彩空间
      let gray = this.createMat(cv, 2);
      cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY);

      // 计算灰度图的极值和位置
      // 和 C++,Python 程序运行的结果不一致,感到很奇怪
      if (gray.type() === cv.CV_8UC1) {
        let ret = cv.minMaxLoc(gray);
        console.log(ret);
      }

      // 计算彩色图的均值和方差
      let bgr = this.createMat(cv, 2);
      cv.cvtColor(src, bgr, cv.COLOR_RGBA2BGR);
      let means = this.createMat(cv, 2);
      let stddev = this.createMat(cv, 2);
      cv.meanStdDev(bgr, means, stddev);
      //   this.showImgInfo(means)
      //   this.showImgInfo(stddev)
      // 和 C++,Python 程序运行的结果不一致,感到很奇怪
      console.log(`blue channel -> mean: ${means.ucharAt(0, 0)}, stddev: ${stddev.ucharAt(0, 0)}`);
      console.log(`green channel -> mean: ${means.ucharAt(1, 0)}, stddev: ${stddev.ucharAt(1, 0)}`);
      console.log(`red channel -> mean: ${means.ucharAt(2, 0)}, stddev: ${stddev.ucharAt(2, 0)}`);

      // 显示图像
      cv.imshow("canvasOutput", gray);

      // 销毁所有 mat
      this.destoryAllMats();
    },
    createMat(cv, type, ops) {
      switch (type) {
        case 1:
          if (ops && ops.name) {
            let mat = cv.imread(ops.name);
            this.mats.push(mat);
            return mat;
          }
          break;
        case 2: {
          let mat = new cv.Mat();
          this.mats.push(mat);
          return mat;
        }
        case 3:
          if (ops && ops.rows && ops.cols && ops.type && ops.initValue) {
            let mat = new cv.Mat(ops.rows, ops.cols, ops.type, ops.initValue);
            this.mats.push(mat);
            return mat;
          }
          break;
        default:
          break;
      }
    },
    showImgInfo(src) {
      console.log("img size :", src.size());
      console.log("img type :", src.type());
      console.log("img cols :", src.cols);
      console.log("img rows :", src.rows);
      console.log("img depth:", src.depth());
      console.log("img channels:", src.channels());
    },
    destoryAllMats() {
      let i = 0;
      this.mats.forEach((item) => {
        item.delete();
        i++;
      });
      console.log("销毁图象数:", i);
    },
  },
};
</script>

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

补充说明:我并没有在官方文档中找到这次的 js 版本的 API 说明。更显奇怪的是,js 的统计结果和 c++ 还有 Python 的统计结果是不一致的,但 c++ 和 python 的结果是一致的,如果有小伙伴知道原因,欢迎私信我或给我留言。

结果展示

返回总目录

OpenCV4学习笔记 - 目录

如果这篇文章对您有帮助,欢迎给我的 github项目 点一个⭐ ο(=•ω<=)ρ⌒☆

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Apple_Coco

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值