05 图像像素的算术操作
05 图像像素的算术操作
opencv知识点:
-
图像像素算术操作 - 运算符
-
值的截断 - saturate_cast<>()
-
图像像素算术操作 - 专用函数
本课所解决的问题:
- 如何改变图像的亮度?
- 如何进行图像像素的算术操作?
- 如何对可能溢出的值进行截断?
1.改变图像亮度
对于改变图像的亮度,我们可以采用图像像素的算术操作实现
本文采用如下两种方法演示
- 四种运算运算符
- 四种专用函数
2.四种运算符和截断
运算符(调节图像的亮度的几种方法)#
首先,我们采用运算符的方式 (调节亮度)
程序#
main.cpp#
#include "opencv2/opencv.hpp"
#include "quickopencv.h"
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("C:/Users/LZQ/Desktop/lena.png"); // B, G, R
if (src.empty()) {
printf("could not load image....\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO);
imshow("输入窗口", src);
QuickDemo qd;
qd.operators_demo(src); //05 <---------------------------修改的程序(唯一的修改部分)
waitKey(0);
destroyAllWindows();
return 0;
}
quickdemo.cpp#
#include "quickopencv.h"
#include <opencv2/dnn.hpp>
using namespace cv;
using namespace std;
void QuickDemo::operators_demo(Mat& image) {
Mat dst;
dst = image + Scalar(50, 50, 50); //加法操作
//dst = image - Scalar(50, 50, 50); //减法操作
//dst = image * Scalar(5, 5, 5);//会溢出 //乘法操作
//dst = image / Scalar(5, 5, 5);//会截断为0 //除法操作
imshow("加法操作", dst);
quickopencv.h#
pragma once
#include <opencv2/opencv.hpp>
using namespace cv;
class QuickDemo { //快速的演示文件 class类
public:
void operators_demo(Mat& image); // <-----------------修改的程序(唯一的修改部分)
};
结果#
加法:#
图像变亮,可能会溢出
减法:#
图像变暗,会自动截断为0
乘法:#
可能会溢出,提示溢出的错误。
本案例就溢出了,所以没有结果展示
除法:#
除法:如果除数较大,结果最终会被自动截断为0
截断函数#
采用运算符时加法,乘法有溢出隐患,有什么办法解决吗?
这就用到了saturate_cast<uchar>
,当使用它时会保证BGR图像的像素值在[0,255]
对于截断的演示,我们用运算符加法演示
quickdemo.cpp#
其余的程序和上面一样
#include "quickopencv.h"
#include <opencv2/dnn.hpp>
using namespace cv;
using namespace std;
void QuickDemo::operators_demo(Mat& image) {
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(50, 50, 50);
int h = image.rows;
int w = image.cols;
int dims = image.channels();
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
Vec3b p1 = image.at<Vec3b>(row, col);
Vec3b p2 = m.at<Vec3b>(row, col);
dst.at<Vec3b>(row,col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);
dst.at<Vec3b>(row,col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);
dst.at<Vec3b>(row,col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);
}
}
imshow("加法操作", dst);
}
3.专用函数
有没有更简单的方式呢?
OpenCV有自带的专用函数,专用函数都有截断处理,以乘法为例。
quickdemo.cpp#
其余部分的程序不变。
#include "quickopencv.h"
#include <opencv2/dnn.hpp>
using namespace cv;
using namespace std;
void QuickDemo::operators_demo(Mat& image) {
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(50, 50, 50);
//add(image, m, dst);
//subtract(image, m, dst);
multiply(image, m,dst);
//divide(image, m, dst);
imshow("加法操作", dst);
}
本课所用API查阅
Scalar()#
add()#
subtract()#
multiply()#
divide()#
saturate_cast<>()#
uchar a = saturate_cast<uchar>(-100); // a = 0 (UCHAR_MIN)
short b = saturate_cast<short>(33333.33333); // b = 32767 (SHRT_MAX)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步