OpenCv之两图像像素操作与运算

目录

一、逐像素比较函数

[1.1 cv::min()](#1.1 cv::min())

[1.2. cv::max()](#1.2. cv::max())

[1.3 典型的用途](#1.3 典型的用途)

1.3.1图像融合与增强

[1.3.2 图像蒙版与取区域提](#1.3.2 图像蒙版与取区域提)

[1.3.3 多帧图像降噪](#1.3.3 多帧图像降噪)

[1.3.4 图像对比与差异检测](#1.3.4 图像对比与差异检测)

[1.4 简单应用举例](#1.4 简单应用举例)

[1.4.1 对图片噪声的抑制](#1.4.1 对图片噪声的抑制)

[1.4.2 图片亮度调整](#1.4.2 图片亮度调整)

[1.4.3 亮区提取](#1.4.3 亮区提取)

二、图像中极值查找

[2.1cv::minMaxLoc() 定义](#2.1cv::minMaxLoc() 定义)

[2.2 典型用途](#2.2 典型用途)

2.3简单应用举例

三、图像像素逻辑运算

3.1像素位运算介绍

3.2核心函数典型使用场景

[3.2.1 bitwise_not(按位取反 / 反色)](#3.2.1 bitwise_not(按位取反 / 反色))

[3.2.2 bitwise_and(按位与)](#3.2.2 bitwise_and(按位与))

[3.2.3 bitwise_or(按位或)](#3.2.3 bitwise_or(按位或))

[3.2.4. bitwise_xor(按位异或)](#3.2.4. bitwise_xor(按位异或))

[3.3 简单应用举例](#3.3 简单应用举例)

[3.3.1 抠图提取图片的亮区或者暗区](#3.3.1 抠图提取图片的亮区或者暗区)

[3.3.2 图片简单添加水印](#3.3.2 图片简单添加水印)


在实际应用中图像由于拍摄环境等等原因会导致图像细节不清晰,对于连续多次抓拍的图片可以利用不同图片不同之处进行细节互补从而达到图像增强的目的。

一、逐像素比较函数

1.1 cv::min()

复制代码
void cv::min(InputArray src1, InputArray src2, OutputArray dst);
  • 作用 :对两个输入图像 src1src2 进行逐像素比较,在每个位置取较小 的像素值,输出到 dst
  • 要求src1src2 必须尺寸、通道数、数据类型完全一致。
  • 结果dst 与输入图像尺寸、通道数、类型相同,每个像素是对应位置两图中较小的值。

1.2. cv::max()

复制代码
void cv::max(InputArray src1, InputArray src2, OutputArray dst);
  • 作用 :对两个输入图像 src1src2 进行逐像素比较,在每个位置取较大 的像素值,输出到 dst
  • 要求 :与 min() 相同,src1src2 必须尺寸、通道数、数据类型完全一致。
  • 结果dst 与输入图像尺寸、通道数、类型相同,每个像素是对应位置两图中较大的值。

1.3 典型的用途

1.3.1图像融合与增强

max():常用于 "亮部融合",将两张曝光不同的照片融合,保留更亮的细节(如夜景 + 补光)。

min():常用于 "暗部融合",保留更暗的细节,或用于图像去噪(取多次拍摄的最小值)。

1.3.2 图像蒙版与取区域提

与阈值图像比较,提取亮区或暗区,例如 max(img, threshold_img) 可以保留亮于阈值的区域,暗于阈值的区域被阈值覆盖。

1.3.3 多帧图像降噪

对同一目标拍摄多张图像,取 min() 或 max() 可以有效抑制随机噪声。

1.3.4 图像对比与差异检测

通过 max(img1 - img2, img2 - img1) 可以得到两幅图像的差异图,用于变化检测。

1.4 简单应用举例

1.4.1 对图片噪声的抑制

cpp 复制代码
// 生成椒盐噪声图像
Mat addSaltPepperNoise(const Mat& src, float noiseRatio = 0.02) {
	Mat noisyImg = src.clone();
	int noiseNum = src.total() * noiseRatio; // 噪声像素数量

	// 添加盐噪声(亮噪声,像素值255)
	for (int i = 0; i < noiseNum / 2; i++) {
		int x = rand() % src.cols;
		int y = rand() % src.rows;
		if (src.channels() == 1) { // 灰度图
			noisyImg.at<uchar>(y, x) = 255;
		}
		else { // 彩色图(BGR)
			noisyImg.at<Vec3b>(y, x)[0] = 255;
			noisyImg.at<Vec3b>(y, x)[1] = 255;
			noisyImg.at<Vec3b>(y, x)[2] = 255;
		}
	}

	// 添加椒噪声(暗噪声,像素值0)
	for (int i = 0; i < noiseNum / 2; i++) {
		int x = rand() % src.cols;
		int y = rand() % src.rows;
		if (src.channels() == 1) {
			noisyImg.at<uchar>(y, x) = 0;
		}
		else {
			noisyImg.at<Vec3b>(y, x)[0] = 0;
			noisyImg.at<Vec3b>(y, x)[1] = 0;
			noisyImg.at<Vec3b>(y, x)[2] = 0;
		}
	}
	return noisyImg;
}

int testMinAndMax1(){
	// 1. 读取单张原图
	Mat img = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_COLOR);
	if (img.empty()) {
		cout << "图像读取失败!" << endl;
		return -1;
	}

	// 2. 生成带椒盐噪声的变体图
	Mat noisyImg = addSaltPepperNoise(img, 0.03); // 3%噪声比例

	// 3. min/max 融合
	Mat maxFused, minFused,maxminFused;
	max(img, noisyImg, maxFused); // 保留亮像素,抑制暗噪声(椒噪声)
	min(img, noisyImg, minFused); // 保留暗像素,抑制亮噪声(盐噪声)

	// 4. 显示结果
	imshow("原图", img);
	imshow("带噪声图", noisyImg);
	imshow("max融合(抑制暗噪声)", maxFused);
	imshow("min融合(抑制亮噪声)", minFused);

	waitKey(0);
	destroyAllWindows();
	return 0;
}

1.4.2 图片亮度调整

cpp 复制代码
/ 调整图像亮度(delta>0调亮,delta<0调暗)
Mat adjustBrightness(const Mat& src, int delta) {
	Mat brightImg;
	src.convertTo(brightImg, -1, 1, delta); // 1倍对比度,delta亮度偏移
	return brightImg;
}

int testMinAndMax2() {
	// 1. 读取单张原图
	Mat img = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_COLOR);
	if (img.empty()) {
		cout << "图像读取失败!" << endl;
		return -1;
	}

	// 2. 生成亮度变体图
	Mat brightImg = adjustBrightness(img, 50);  // 调亮50
	Mat darkImg = adjustBrightness(img, -50);   // 调暗50

	// 3. min/max 融合
	Mat maxFused, minFused;
	max(img, brightImg, maxFused); // 原图+调亮图取最大值,整体更亮
	min(img, darkImg, minFused);   // 原图+调暗图取最小值,整体更暗

	// 4.调亮图+调暗图融合(模拟曝光融合)
	Mat exposureFused;
	max(brightImg, darkImg, exposureFused);

	// 5. 显示结果
	imshow("原图", img);
	imshow("调亮图", brightImg);
	imshow("调暗图", darkImg);
	imshow("max融合(整体提亮)", maxFused);
	imshow("min融合(整体压暗)", minFused);
	imshow("曝光融合(亮部+暗部)", exposureFused);
	waitKey(0);
	destroyAllWindows();
	return 0;
}

1.4.3 亮区提取

cpp 复制代码
void testMinAndMax3() {
	// 1. 读取原图(默认:CV_8UC3,3通道彩色图)
	Mat img = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_COLOR);
	if (img.empty()) { // 新增:必加的空值校验,避免后续崩溃
		cout << "图像读取失败,请检查路径!" << endl;
		return;
	}

	// 2. 创建阈值图像:匹配原图的【数据类型】和【通道数】
	// CV_8UC3:8位无符号字符 + 3通道;Scalar(128,128,128):3通道都设为128
	Mat threshold_img(img.size(), CV_8UC3, Scalar(128, 128, 128));

	Mat bright_regions, dark_regions;
	max(img, threshold_img, bright_regions); // 亮于128保留原值,暗于128设为128
	min(img, threshold_img, dark_regions);   // 暗于128保留原值,亮于128设为128

	imshow("亮区提取", bright_regions);
	imshow("暗区提取", dark_regions);
	waitKey(0);
	destroyAllWindows();
}

二、图像中极值查找

2.1cv::minMaxLoc() 定义

cv::minMaxLoc() 是 OpenCV 中用于在单通道图像中查找最小值、最大值及其对应坐标的专用函数。

cpp 复制代码
void cv::minMaxLoc(
    InputArray src,
    double* minVal,
    double* maxVal = 0,
    Point* minLoc = 0,
    Point* maxLoc = 0,
    InputArray mask = noArray()
);
参数 说明
src 输入单通道矩阵(如灰度图、单通道掩膜等)。多通道图像需先分离通道。
minVal 输出型参数,指向最小值的指针。若不需要,可传 NULL
maxVal 输出型参数,指向最大值的指针。若不需要,可传 NULL
minLoc 输出型参数,指向最小值位置(Point(x,y))的指针。若不需要,可传 NULL
maxLoc 输出型参数,指向最大值位置(Point(x,y))的指针。若不需要,可传 NULL
mask 可选掩膜矩阵,用于限定查找范围。默认 noArray(),表示在全图中查找。

2.2 典型用途

  • 图像亮度分析:快速定位图像中最亮 / 最暗区域,用于曝光评估或自动曝光控制。
  • 目标检测与定位 :在模板匹配(matchTemplate)或特征检测的响应图中,通过极值点定位目标位置。
  • 阈值与分割验证:在阈值处理或图像分割后,验证分割结果的极值,判断是否有效。
  • 局部特征分析 :结合 mask 参数,在图像的特定区域(如 ROI)内分析极值。

2.3简单应用举例

找寻图片中最亮和最暗的部分

cpp 复制代码
int testminMaxLoc1() {
	// 1. 读取为单通道灰度图
	Mat img = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_GRAYSCALE);
	if (img.empty()) {
		cout << "图像读取失败!" << endl;
		return -1;
	}

	// 2. 定义变量存储结果
	double minVal, maxVal;
	Point minLoc, maxLoc;

	// 3. 调用 minMaxLoc
	minMaxLoc(img, &minVal, &maxVal, &minLoc, &maxLoc);

	// 4. 输出结果
	cout << "最小值: " << minVal << " @ " << minLoc << endl;
	cout << "最大值: " << maxVal << " @ " << maxLoc << endl;

	// 可视化:在极值点画圆标记
	Mat imgColor;
	cvtColor(img, imgColor, COLOR_GRAY2BGR);//格式转换所有通道填充值一样
	circle(imgColor, minLoc, 5, Scalar(255, 0, 0), 2); // 蓝色圈标最小值
	circle(imgColor, maxLoc, 5, Scalar(0, 0, 255), 2); // 红色圈标最大值
	imshow("极值点标记", imgColor);
	waitKey(0);
	return 0;
}

三、图像像素逻辑运算

3.1像素位运算介绍

像素位运算直接操作图像像素的二进制位(8 位图像对应 0~255 的二进制),是图像处理中掩膜操作、区域提取、图像合成 的基础。OpenCV 中像素位运算函数主要有: bitwise_and/or/not/xor。

函数名 核心逻辑 公式(8 位图像) 关键要求
bitwise_not 按位取反(反色) dst = ~src = 255 - src 单输入图像
bitwise_and 按位与(仅双 1 为 1) dst = src1 & src2 src1/src2 尺寸 / 类型完全一致
bitwise_or 按位或(有 1 则 1) `dst = src1 src2` src1/src2 尺寸 / 类型完全一致
bitwise_xor 按位异或(不同为 1,相同为 0) dst = src1 ^ src2 src1/src2 尺寸 / 类型完全一致

函数原型以bitwisw_and为例:

cpp 复制代码
void bitwise_and(
    InputArray src1,    // 输入图像1(原图/掩膜)
    InputArray src2,    // 输入图像2(掩膜/原图)
    OutputArray dst,    // 输出图像(与输入尺寸/类型一致)
    InputArray mask = noArray()  // 可选:仅掩膜非零区域执行运算
);

3.2核心函数典型使用场景

3.2.1 bitwise_not(按位取反 / 反色)

  • 作用:将每个像素值取反,生成 "底片效果";也用于反转掩膜(黑↔白)。
  • 核心场景
    • 图像反色(如校正颜色反转的摄像头画面);
    • 掩膜反转(将 "黑底白目标" 的掩膜转为 "白底黑目标");
    • 工业检测中突出暗背景下的亮缺陷。

3.2.2 bitwise_and(按位与)

  • 作用 :仅当两个像素对应位都为 1 时结果为 1,核心用于掩膜提取(ROI 抠图)
  • 核心场景
    • 掩膜抠图(用黑白掩膜保留原图指定区域,屏蔽背景);
    • 多条件筛选(同时满足两个阈值的区域保留);
    • 图像合成(仅保留两张图的交集区域)。

3.2.3 bitwise_or(按位或)

  • 作用 :只要有一个像素对应位为 1 结果为 1,核心用于图像融合 / 区域合并
  • 核心场景
    • 多区域合并(将多个掩膜的目标区域合并为一个);
    • 图像叠加(保留两张图的所有非零区域);
    • 缺陷标记(将检测到的多个缺陷区域叠加到原图)。

3.2.4. bitwise_xor(按位异或)

  • 作用 :像素值不同则为 1,相同则为 0,核心用于差异检测 / 水印隐藏
  • 核心场景
    • 图像差异检测(对比两张相似图,高亮不同区域);
    • 水印添加 / 提取(异或加密水印,再次异或可还原);
    • 动态目标检测(背景建模后,异或提取运动目标)。

3.3 简单应用举例

3.3.1 抠图提取图片的亮区或者暗区

cpp 复制代码
void testBinaryOperator() {
	// 1. 读取图像并预处理
	Mat img = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_COLOR);
	if (img.empty()) { cout << "图像读取失败!" << endl; return; }
	Mat gray;
	cvtColor(img, gray, COLOR_BGR2GRAY); // 转灰度图

	// 2. 生成掩膜(提取亮度>150的区域)
	Mat mask;
	threshold(gray, mask, 150, 255, THRESH_BINARY); // 亮区白,暗区黑

	// 3. bitwise_not:反转掩膜
	Mat mask_not;
	bitwise_not(mask, mask_not); // 亮区黑,暗区白

	// 4. bitwise_and:掩膜抠图
	Mat result_bright, result_dark;
	// 提取亮区:mask为白的区域保留原图,黑的区域置0
	bitwise_and(img, img, result_bright, mask);//自身image与操作图像不变 在与mask掩膜
	// 提取暗区:用反转后的掩膜提取暗部
	bitwise_and(img, img, result_dark, mask_not);

	// 5. 显示结果
	imshow("原图", img);
	imshow("掩膜(亮区白)", mask);
	imshow("反转掩膜(暗区白)", mask_not);
	imshow("提取亮区", result_bright);
	imshow("提取暗区", result_dark);
	waitKey(0);
	destroyAllWindows();
}

3.3.2 图片简单添加水印

cpp 复制代码
int testBinaryOperator2() {
	// 读取原图和水印图
	Mat img = imread(R"(D:\Study\OpenCvStudy\lean.jpg)", ImreadModes::IMREAD_COLOR);  // 背景图
	Mat logo = imread(R"(D:\Study\OpenCvStudy\White.png)", IMREAD_UNCHANGED);
	if (img.empty() || logo.empty()) return -1;

	// 分离水印的BGR通道和Alpha通道(透明度)
	std::vector<Mat> layers;
	split(logo, layers);
	// 提取BGR三通道,合并为彩色水印图
	vector<Mat> bgr_layers = { layers[0], layers[1], layers[2] };
	Mat logo_bgr;
	merge(bgr_layers, logo_bgr);
	Mat alpha = layers[3];    // Alpha通道(0=透明,255=不透明)

	// 定义水印在原图中的位置(左上角)
	Rect roi(50, 50, logo.cols, logo.rows);
	Mat img_roi = img(roi); // 原图中对应区域

	// 生成掩膜:用于挖空原图
	Mat mask;
	bitwise_not(alpha, mask); // 透明区域变白,不透明区域变黑

	//从原图中"挖去"水印位置
	Mat img_bg;
	bitwise_and(img_roi, img_roi, img_bg, mask);

	// 从水印中"抠出"水印内容
	Mat logo_fg;
	bitwise_and(logo_bgr, logo_bgr, logo_fg, alpha);

	// 合并:挖去的背景 + 抠出的水印
	Mat blended;
	//add(img_bg, logo_fg, blended);完全堆叠无透明效果
	double alpha_weight = 0.3; // 水印透明度:0.0(全透)~ 1.0(不透明)
	addWeighted(img_roi, 1 - alpha_weight, logo_fg, alpha_weight, 0, blended);

	//将结果放回原图
	blended.copyTo(img_roi);

	imshow("带水印效果", img);
	waitKey(0);
	return 0;
}
相关推荐
无心水2 小时前
【OpenClaw:源码解析】15、OpenClaw Gateway 大脑中枢——dispatch_task 函数与消息队列设计探秘
人工智能·arcgis·系统架构·openclaw·openclaw·三月创作之星·ai前沿
格林威2 小时前
工业相机图像高速存储(C++版):先存内存,后批量转存方法,附海康相机实战代码!
开发语言·c++·人工智能·数码相机·计算机视觉·工业相机·堡盟相机
啊阿狸不会拉杆2 小时前
《计算机视觉:模型、学习和推理》第 19 章-时序模型
人工智能·python·学习·机器学习·计算机视觉·时序模型
Mintopia2 小时前
如何看待大模型发展瓶颈:从算力、数据到对齐与系统工程的再评估
前端·人工智能
Lxt12138_2 小时前
2026深耕学术,智启创作——论文创作如何正确使用新兴科技
人工智能·科技
x-cmd2 小时前
[260311] x-cmd v0.8.8:新增一键卸载 OpenClaw 命令,AI 命令补全回归,内网服务器一键部署 x-cmd
运维·服务器·人工智能·ai·ssh·x-cmd·openclaw
云梦谭2 小时前
AI如何重塑通信行业:从VoIP到智能语音平台
人工智能
翼龙云_cloud2 小时前
阿里云代理商:如何用百炼自动生成商品解说视频?
人工智能·阿里云·云计算
新科技事物2 小时前
原创音乐人制作编曲伴奏新方式,清唱歌词的音频搭配AI编曲软件更高效出歌
人工智能·音视频