图像实验1-灰度变换
一、实验目的
掌握 Opencv 进行图像处理的基础,实现图像的灰度变换处理。
1、掌握 OpenCV 的安装
2、掌握 OpenCV 对图像进行基本操作
3、掌握利用 OpenCV 对图像进行灰度变换
二、实验内容
1、利用 OpenCV 读取图像
具体内容:用打开 OpenCV 打开图像,并在窗口中显示
2、灰度图像二值化处理
具体内容:设置并调整阈值对图像进行二值化处理。
3、灰度图像的对数变换
具体内容:设置并调整 r 值对图像进行对数变换。
4、灰度图像的伽马变换
具体内容:设置并调整γ值对图像进行伽马变换。
5、彩色图像的补色变换
具体内容:对彩色图像进行补色变换。
三、实验完成情况
1、利用 OpenCV 读取图像
核心代码
//统一图片打开函数,用于简化路径和处理打开图片错误
Mat openImage(string name,int type = 1) {
//图片读取函数,返回图像存储类(包含存储方式、存储矩阵、矩阵大小等)
Mat img = imread(getFullPath(name),type);
if (img.empty()) {
cout << "无效图片,读取失败" << endl;
exit(-1);
}
return img;
}
//打开图片显示窗口
void openWindows(string win_name, Mat img, int x = 500, int y = 500, bool close_window = true) {
//窗口命名,指定大小,生成位置
namedWindow(win_name, WINDOW_AUTOSIZE);
moveWindow(win_name, x, y);
//生成窗口显示图片
imshow(win_name, img);
//等待键入
waitKey();
//关闭窗口
destroyWindow(win_name);
}
实现截图
2.灰度图像二值化处理
核心代码
//灰度二值化处理,灰度阀值输入获取,最大值默认255
Mat handleBinary(int gray, int max = 255) {
Mat result;
//灰度处理,方式为二值化(THRESH_BINARY)
threshold(img, result, gray, max, THRESH_BINARY);
return result;
}
实现截图
3、灰度图像的对数变换
核心代码
//灰度对数变换,c值默认1
Mat handleLogarithmic(int c = 1) {
//复制图像
Mat src = img.clone();
//图像元素变换为32F浮点类型
src.convertTo(src, CV_32F);
//建立空白目标图像结构
Mat target = Mat::zeros(img.size(), img.type());
//1+r 原图像与标量相加,由于是灰度图像,因此标量为Scalar(1.0),等同于src = src+1
add(src, Scalar(1.0), src);
//log(1+r) 对数变换
log(src, target);
//clog(1+r)
target *= c;
//归一化处理,即将变换后的图像平移、缩放到指定区间(0,255),归一化方式为最小值和最大值范围(NORM_MINMAX)
normalize(target, target, 0, 255, NORM_MINMAX);
//图像增强取绝对值并变换为U8整数类型,此处等同于target.convertTo(target, CV_8U);
convertScaleAbs(target, target);
return target;
}
实现截图
4、灰度图像的伽马变换
核心代码
//灰度伽马变换,gamma值默认1
Mat handleGamma(double gamma = 1.0) {
//复制图像
Mat target = img.clone();
//图像元素变换为64F浮点类型,并缩放到0~1区间内方便进行伽马变换
target.convertTo(target, CV_64F, 1.0 / 255.0);
//伽马变换
pow(target, gamma, target);
//图像元素缩放回0-255区间并变换为8U整数类型
target.convertTo(target, CV_8U, 255.0);
return target;
}
实现截图
5、彩色图像的补色变换
核心代码
//反色变换,采用255-RGB方式,非补色
//Mat handleComplementary() {
// Mat target = img.clone();
// target = Scalar(255,255,255,255) - target; //Scalar::all(255)
// return target;
//}
//补色变换,采用255-RGB方式
Mat handleComplementary() {
Mat target = img.clone();
//将RGB转换为HSV
cvtColor(target, target, COLOR_BGR2HSV);
// target = Scalar(255,255,255,255) - target; //Scalar::all(255) RGB反色
vector<Mat> mats;
//分离图层
split(target, mats);
//色彩层补色处理
mats[0] = Scalar::all(180) - mats[0];
//将处理过的色彩层合并到图像中
merge(mats, target);
return target;
}
实现截图
四、实验中的问题
- 已安装的VS2019组建损坏,无法完成正常的C++编译,因此重新安装了VS2019
- 实验指导中给定版本较旧,因此采用最新版本的OpenCV-4.5.2+VS2019进行实验,有很多地方与实验指导不一致,根据网上的教程进行环境配置。
- 重新熟悉C++耗费了一定时间和精力。
五、实验结果
源码
lab1.cpp
#include <opencv2/opencv.hpp>
#include <iostream>
#include <string>
#include "configs.h"
using namespace std;
using namespace cv;
const static std::string path = "F:\\Documents\\高级图像处理\\Image\\";
//图片路径组合
string getFullPath(string name) {
return path + name;
}
//打开图片显示窗口
void openWindows(string win_name, Mat img, int x = 500, int y = 500, bool close_window = true) {
//窗口命名,指定大小,生成位置
namedWindow(win_name, WINDOW_AUTOSIZE);
moveWindow(win_name, x, y);
//生成窗口显示图片
imshow(win_name, img);
//等待键入
waitKey();
//关闭窗口
destroyWindow(win_name);
}
//统一数字输入函数
template<typename T>T inputNumber(string desc) {
system("cls");
T input;
cout << desc;
cin >> input;
cout << endl;
return input;
}
//统一图片打开函数,用于简化路径和处理打开图片错误
Mat openImage(string name,int type = 1) {
//图片读取函数,返回图像存储类(包含存储方式、存储矩阵、矩阵大小等)
Mat img = imread(getFullPath(name),type);
if (img.empty()) {
cout << "无效图片,读取失败" << endl;
exit(-1);
}
return img;
}
//彩色图像处理类
class ColorImage {
private:
Mat img;
//补色变换,采用255-RGB方式
Mat handleComplementary() {
Mat target = img.clone();
//将RGB转换为HSV
cvtColor(target, target, COLOR_BGR2HSV);
// target = Scalar(255,255,255,255) - target; //Scalar::all(255) RGB反色
vector<Mat> mats;
//分离图层
split(target, mats);
//色彩层补色处理
mats[0] = Scalar::all(180) - mats[0];
//将处理过的色彩层合并到图像中
merge(mats, target);
return target;
}
public:
//读取彩色图像并展示
ColorImage(string path) {
img = openImage(path, IMREAD_COLOR);
openWindows("彩色图像", img, false);
}
//补色变换接口
void complementaryColorTransform() {
openWindows("彩色补色图像", handleComplementary());
}
};
//灰度图像处理类
class GrayImage {
private:
Mat img;
//灰度二值化处理,灰度阀值输入获取,最大值默认255
Mat handleBinary(int gray, int max = 255) {
Mat result;
//灰度处理,方式为二值化(THRESH_BINARY)
threshold(img, result, gray, max, THRESH_BINARY);
return result;
}
//灰度对数变换,c值默认1
Mat handleLogarithmic(int c = 1) {
//复制图像
Mat src = img.clone();
//图像元素变换为32F浮点类型
src.convertTo(src, CV_32F);
//建立空白目标图像结构
Mat target = Mat::zeros(img.size(), img.type());
//1+r 原图像与标量相加,由于是灰度图像,因此标量为Scalar(1.0),等同于src = src+1
add(src, Scalar(1.0), src);
//log(1+r) 对数变换
log(src, target);
//clog(1+r)
target *= c;
//归一化处理,即将变换后的图像平移、缩放到指定区间(0,255),归一化方式为最小值和最大值范围(NORM_MINMAX)
normalize(target, target, 0, 255, NORM_MINMAX);
//图像增强取绝对值并变换为U8整数类型,此处等同于target.convertTo(target, CV_8U);
convertScaleAbs(target, target);
return target;
}
//灰度伽马变换,gamma值默认1
Mat handleGamma(double gamma = 1.0) {
//复制图像
Mat target = img.clone();
//图像元素变换为64F浮点类型,并缩放到0~1区间内方便进行伽马变换
target.convertTo(target, CV_64F, 1.0 / 255.0);
//伽马变换
pow(target, gamma, target);
//图像元素缩放回0-255区间并变换为8U整数类型
target.convertTo(target, CV_8U, 255.0);
return target;
}
public:
//仅读取灰度方式读取图像并展示(IMREAD_GRAYSCALE)
GrayImage(string path) {
img = openImage(path, IMREAD_GRAYSCALE);
openWindows("灰度图像", img, false);
}
//灰度二值化接口,灰度阀值从输入获取
void binaryProcessing() {
int gray = inputNumber<int>("输入灰度阀值:");
openWindows("灰度二值化", handleBinary(gray));
}
//灰度对数变换接口,c值取默认1
void logarithmicTransform() {
openWindows("灰度对数变换", handleLogarithmic());
}
//灰度伽马变换接口,伽马值从输入获取
void gammaTransform() {
double gamma = inputNumber<double>("输入伽马值:");
openWindows("灰度伽马变换", handleGamma(gamma));
}
};
int main(){
//测试彩色图片1
string name = "test.jpg";
//彩色图片处理类
ColorImage color_img(name);
//补色变换
color_img.complementaryColorTransform();
//测试灰度图片
name = "night.jpg";
//灰度图片处理类
GrayImage gray_img(name);
//灰度二值化
gray_img.binaryProcessing();
//对数变换
gray_img.logarithmicTransform();
//伽马变换
gray_img.gammaTransform();
return 0;
}