1. 线框立方体
【问题描述】
请使用 OpenGL、GLU 和 GLUT 编写一个显示线框立方体的程序。其中立方体的半径为 1.5 单位,并首先绕(0, 0, 0)~(1, 1, 0)旋转 30 度,然后远移 6.5 单位;观察体规定为:视场角=30度,宽高比=1,近=1,远=100;程序窗口的大小为(200, 200),标题为“线框立方体”。
【设计思路】
要实现这个功能,我们可以使用OpenGL、GLU和GLUT库来编写一个显示线框立方体的程序。首先,我们需要初始化窗口和OpenGL环境,设置窗口大小为(200, 200),标题为“线框立方体”。然后,我们需要在初始化函数中设置背景颜色、投影矩阵和模型视图矩阵。在显示函数中,我们可以通过调用OpenGL的函数来绘制一个线框立方体,并对其进行旋转和远移操作。最后,在reshape函数中设置投影矩阵,以确保线框立方体在窗口中正确显示。整个程序的主要逻辑是在初始化、显示和重塑函数中完成的。通过使用OpenGL的函数来设置投影矩阵和模型视图矩阵,我们可以实现对立方体的旋转、平移和投影设置。希望这个设计思路能够帮助你完成这个程序。
【关键程序】
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION); // 设置投影矩阵
glLoadIdentity(); // 重置当前矩阵为单位矩阵
gluPerspective(30.0, 1.0, 1.0, 100.0); // 设置透视投影,视场角=30度,宽高比=1,近=1,远=100
glMatrixMode(GL_MODELVIEW); // 设置模型视图矩阵
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清空颜色缓冲区和深度缓冲区
glLoadIdentity(); // 重置当前矩阵为单位矩阵
glTranslatef(0.0, 0.0, -6.5); // 远移6.5单位
glRotatef(30.0, 1.0, 1.0, 0.0); // 绕(1, 1, 0)旋转30度
glutWireCube(3.0); // 绘制线框立方体,半径为1.5
glFlush(); // 刷新绘图
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h); // 设置视口
glMatrixMode(GL_PROJECTION); // 设置投影矩阵
glLoadIdentity(); // 重置当前矩阵为单位矩阵
if (w <= h) {
glOrtho(-3.0, 3.0, -3.0 * (GLfloat)h / (GLfloat)w, 3.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);
}
else {
glOrtho(-3.0 * (GLfloat)w / (GLfloat)h, 3.0 * (GLfloat)w / (GLfloat)h, -3.0, 3.0, -10.0, 10.0);
}
glMatrixMode(GL_MODELVIEW); // 设置模型视图矩阵
}
【实验结果】
2. 线框球
【问题描述】
请使用 OpenGL 和 GLUT 编写一个显示线框球体的简单图形程序。其中球体的半径为 0.8,经线数为 24,纬线数为 12,并绕 轴旋转 30 度,程序窗口的大小为(200, 200),标题“为线框球”。
【设计思路】
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0); // 设置背景颜色为黑色
glShadeModel(GL_FLAT); // 设置着色模式为平面着色
}
void display() {
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
glPushMatrix(); // 保存当前模型视图矩阵
glRotatef(30.0, 1.0, 0.0, 0.0); // 绕x轴旋转30度
glColor3f(1.0, 1.0, 1.0); // 设置颜色为白色
glutWireSphere(0.8, 24, 12); // 绘制线框球体,半径为0.8,经线数为24,纬线数为12
glPopMatrix(); // 恢复之前保存的模型视图矩阵
glFlush(); // 刷新绘图
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h); // 设置视口
glMatrixMode(GL_PROJECTION); // 设置投影矩阵
glLoadIdentity(); // 重置当前矩阵为单位矩阵
if (w <= h) {
gluPerspective(60.0, (GLfloat)h / (GLfloat)w, 1.0, 20.0); // 根据宽高比设置透视投影
}
else {
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0); // 根据宽高比设置透视投影
}
glMatrixMode(GL_MODELVIEW); // 设置模型视图矩阵
glLoadIdentity(); // 重置当前矩阵为单位矩阵
glTranslatef(0.0, 0.0, -5.0); // 平移5个单位到观察点
}
【实验结果】
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0); // 设置背景颜色为黑色
glShadeModel(GL_FLAT); // 设置着色模式为平面着色
}
void display() {
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
glPushMatrix(); // 保存当前模型视图矩阵
glRotatef(30.0, 1.0, 0.0, 0.0); // 绕x轴旋转30度
glColor3f(1.0, 1.0, 1.0); // 设置颜色为白色
glutWireSphere(0.8, 24, 12); // 绘制线框球体,半径为0.8,经线数为24,纬线数为12
glPopMatrix(); // 恢复之前保存的模型视图矩阵
glFlush(); // 刷新绘图
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h); // 设置视口
glMatrixMode(GL_PROJECTION); // 设置投影矩阵
glLoadIdentity(); // 重置当前矩阵为单位矩阵
if (w <= h) {
gluPerspective(60.0, (GLfloat)h / (GLfloat)w, 1.0, 20.0); // 根据宽高比设置透视投影
}
else {
gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0); // 根据宽高比设置透视投影
}
glMatrixMode(GL_MODELVIEW); // 设置模型视图矩阵
glLoadIdentity(); // 重置当前矩阵为单位矩阵
glTranslatef(0.0, 0.0, -5.0); // 平移5个单位到观察点
}
【实验结果】
4. 犹他茶壶
【问题描述】
请使用OpenGL、GLU和GLUT编写一个三维犹他茶壶程序。其中茶壶的半径为1单位,并远移6.5单位;观察体规定为:视场角=30度,宽高比=1,近=1,远=100;程序窗口的大小为(200, 200),标题为“旋转的尤他茶壶”。茶壶绕z方向中轴不断旋转,旋转的时间间隔为25毫秒,角度间隔为2度。注意旋转角度必须限定在0~360度以内。
【设计思路】
static int angle = 0; // 初始旋转角度为0
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色缓冲区和深度缓冲区
glColor3f(1.0, 1.0, 1.0); // 设置颜色为白色
glLoadIdentity(); // 重置当前的模型视图矩阵
gluLookAt(0.0, 0.0, 6.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // 设置观察体
glRotatef((GLfloat)angle, 0.0, 0.0, 1.0); // 绕z轴旋转茶壶
glutWireTeapot(1.0); // 绘制茶壶
glutSwapBuffers(); // 交换前后缓冲区
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h); // 设置视口
glMatrixMode(GL_PROJECTION); // 设置当前矩阵为投影矩阵
glLoadIdentity(); // 重置当前的投影矩阵
gluPerspective(30.0, 1.0, 1.0, 100.0); // 设置透视投影参数
glMatrixMode(GL_MODELVIEW); // 设置当前矩阵为模型视图矩阵
}
void timer(int value) {
angle = (angle + 2) % 360; // 更新旋转角度
glutPostRedisplay(); // 标记窗口需要重新绘制
glutTimerFunc(25, timer, 0); // 25毫秒后再次调用timer函数
}
【实验结果】
5. 多视口演示
【问题描述】
请使用OpenGL、GLU和GLUT编写一个多视口演示程序。要求:(1)在屏幕窗口左下角的1/4部分显示一个红色的填充矩形,该矩形的一对对角顶点是(0, 0)和(1, 1);(2)在屏幕窗口右下角的1/4部分显示一个绿色的填充犹他茶壶,茶壶半径为0.4,并向右向上各移0.5;(3)在屏幕窗口上部居中的1/4部分显示一个蓝色的填充正三角形,该正三角形的左下角顶点是(0, 0),右下角顶点是(1, 0);(4)裁剪窗口均为(-0.1, -0.1)~(1.1, 1.1),程序窗口的大小为(200, 200),背景为黑色,标题为“多视口演示”。
【设计思路】
void display() {
glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区
// 左下角的红色填充矩形
glViewport(0, 0, 100, 100);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 1.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex2f(0.0, 0.0);
glVertex2f(1.0, 0.0);
glVertex2f(1.0, 1.0);
glVertex2f(0.0, 1.0);
glEnd();
// 右下角的绿色填充犹他茶壶
glViewport(100, 0, 100, 100);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-0.1, 1.1, -0.1, 1.1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.5, 0.5, 0.0);
glColor3f(0.0, 1.0, 0.0);
glutSolidTeapot(0.4);
// 上部居中的蓝色填充正三角形
glViewport(50, 100, 100, 100);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 1.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(0.0, 0.0, 1.0);
glBegin(GL_POLYGON);
glVertex2f(0.5, 1.0);
glVertex2f(1.0, 0.0);
glVertex2f(0.0, 0.0);
glEnd();
glutSwapBuffers(); // 交换前后缓冲区
}
【实验结果】
1. 纯白球面在烈日暴晒下的效果
【问题描述】
使用OpenGL和GLUT编写一个程序,用于模拟一个非常光滑的纯白球面在烈日暴晒下的效果。
【设计思路】
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0); // 设置背景颜色为黑色
glEnable(GL_DEPTH_TEST); // 启用深度测试
glEnable(GL_LIGHTING); // 启用光照
glEnable(GL_LIGHT0); // 启用0号光源
glEnable(GL_COLOR_MATERIAL); // 启用材质颜色跟踪
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色缓冲区和深度缓冲区
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; // 光源位置
glLightfv(GL_LIGHT0, GL_POSITION, light_position); // 设置光源位置
glPushMatrix();
glColor3f(1.0, 1.0, 1.0); // 设置颜色为纯白
glutSolidSphere(1.0, 50, 50); // 绘制光滑的纯白球体
glPopMatrix();
glutSwapBuffers(); // 交换前后缓冲区
}
【实验结果】
2. 模拟光照照射紫色球体
【问题描述】
已知在一个空旷的场景中有一个粗糙的紫色球体,球体的右上角方向放置了一个白色的点光源,请使用OpenGL和GLUT编写一个程序模拟出球面上的光照效果(不考虑环境光)。【设计思路】
void init() {
glClearColor(0.0, 0.0, 0.0, 0.0); // 设置背景颜色为黑色
glEnable(GL_DEPTH_TEST); // 启用深度测试
glEnable(GL_LIGHTING); // 启用光照
glEnable(GL_LIGHT0); // 启用0号光源
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 清除颜色缓冲区和深度缓冲区
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// 设置光源位置
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; // 光源位置
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
// 设置材质属性
GLfloat mat_ambient[] = { 0.5, 0.0, 0.5, 1.0 }; // 紫色材质的环境光分量
GLfloat mat_diffuse[] = { 0.5, 0.0, 0.5, 1.0 }; // 紫色材质的漫反射分量
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; // 高光反射颜色为白色
GLfloat mat_shininess[] = { 50.0 }; // 高光反射系数
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glPushMatrix();
glutSolidSphere(1.0, 50, 50); // 绘制紫色的球体
glPopMatrix();
glutSwapBuffers(); // 交换前后缓冲区
}
【实验结果】
1. 实现BMP文件格式的读取功能
【问题描述】
请根据BMP文件的格式编写一个C++函数vector loadBmp24(const string &path)。该函数用于从一个真彩色BMP文件中读取图像数据,保存在uchar数组中(可以忽略非真彩色BMP文件)。
【设计思路】
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdint>
#include <string>
using namespace std;
#pragma pack(push, 1)
struct BMPHeader {
uint16_t type;
uint32_t size;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offset;
uint32_t header_size;
int32_t width;
int32_t height;
uint16_t planes;
uint16_t bit_count;
uint32_t compression;
uint32_t image_size;
int32_t x_pixels_per_meter;
int32_t y_pixels_per_meter;
uint32_t colors_used;
uint32_t colors_important;
};
#pragma pack(pop)
vector<uchar> loadBmp24(const string &path) {
vector<uchar> image_data;
ifstream file(path, ios::in | ios::binary);
if (!file) {
cerr << "Error: Unable to open file " << path << endl;
return image_data;
}
BMPHeader header;
file.read(reinterpret_cast<char*>(&header), sizeof(header));
if (header.type != 0x4D42) {
cerr << "Error: File is not a BMP image" << endl;
return image_data;
}
if (header.bit_count != 24 || header.compression != 0) {
cerr << "Error: Not a 24-bit uncompressed BMP image" << endl;
return image_data;
}
file.seekg(header.offset, ios::beg);
int padding = (4 - ((header.width * 3) % 4)) % 4; // 计算每行的填充字节数
for (int y = 0; y < header.height; y++) {
for (int x = 0; x < header.width; x++) {
uint8_t pixel[3];
file.read(reinterpret_cast<char*>(pixel), 3);
image_data.push_back(pixel[2]); // 保存B分量
image_data.push_back(pixel[1]); // 保存G分量
image_data.push_back(pixel[0]); // 保存R分量
}
file.seekg(padding, ios::cur); // 跳过填充字节
}
file.close();
return image_data;
}
【实验结果】
这个函数首先打开BMP文件并读取文件头信息。接着,它检查文件头中的信息以确保文件是24位真彩色格式且没有压缩。然后,它跳过文件头和调色板数据,直接读取图像数据,并按照BGR顺序保存到vector数组中。最后返回图像数据数组。
2. 使用OpenCV显示指定矩形区域的图像
【问题描述】
使用OpenCV装入一幅大小至少为512×512的真彩色图像,并显示该图像。然后在源图像中指定一个矩形区域(左上顶点和宽高值分别为(128, 256)和(256, 128)的矩形),并在结果图像窗口中显示源图像中被选取的部分。
【设计思路】
int main()
{
Mat img = imread("D:/xm.jpg", IMREAD_COLOR);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Rect roi(128, 256, 256, 128);
Mat cropped = img(roi);
namedWindow("Cropped Image", WINDOW_NORMAL);
imshow("Cropped Image", cropped);
waitKey(0);
return 0;
}
【实验结果】
3. 使用OpenCV分离彩色图像的三个通道并显示灰度图像
【问题描述】
请使用OpenCV编写一个简单的程序,该程序首先读入一幅真彩色图像,然后将这幅彩色图像的3个通道分离出来,得到3幅灰度图像,最后显示这3幅灰度图像。
【设计思路】
int main()
{
Mat img = imread("D:/xm.jpg", IMREAD_COLOR);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat channels[3];
split(img, channels);
namedWindow("Blue Channel", WINDOW_NORMAL);
imshow("Blue Channel", channels[0]);
namedWindow("Green Channel", WINDOW_NORMAL);
imshow("Green Channel", channels[1]);
namedWindow("Red Channel", WINDOW_NORMAL);
imshow("Red Channel", channels[2]);
waitKey(0);
return 0;
}
【实验结果】
4. 使用OpenCV处理灰度图像
【问题描述】
首先使用OpenCV装入一幅灰度图像并显示该图像,然后计算出该图像的最小像素值min和最大像素值max,最后将每个像素都减去min再乘以255/max以后显示结果图像。
【设计思路】
int main()
{
Mat img = imread("D:/xm.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
double minVal, maxVal;
minMaxLoc(img, &minVal, &maxVal);
Mat result;
img.convertTo(result, CV_8U, 255.0 / (maxVal - minVal), -255.0 * minVal / (maxVal - minVal));
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
5. 随机生成并处理浮点数灰度图像
【问题描述】
随机生成一幅浮点数灰度图像(大小和亮度都是随机的,大小值位于区间[128, 639]),然后将该图像变换成亮度是0~1的浮点数图像,最后变换成字节图像并显示该图像。
【设计思路】
int main() {
// 生成随机大小和亮度的浮点数灰度图像
cv::RNG rng;
int width = rng.uniform(128, 640);
int height = rng.uniform(128, 640);
cv::Mat floatImage = cv::Mat::zeros(height, width, CV_32FC1);
rng.fill(floatImage, cv::RNG::UNIFORM, 0.0, 1.0);
// 显示浮点数灰度图像
cv::namedWindow("Float Image", cv::WINDOW_NORMAL);
cv::imshow("Float Image", floatImage);
cv::waitKey(0);
// 将浮点数图像转换为字节图像
cv::Mat byteImage;
floatImage.convertTo(byteImage, CV_8U, 255.0);
// 显示转换后的字节图像
cv::namedWindow("Byte Image", cv::WINDOW_NORMAL);
cv::imshow("Byte Image", byteImage);
cv::waitKey(0);
return 0;
}
【实验结果】
1. 使用OpenCV进行图像缩放变换
【问题描述】
使用OpenCV编写一个演示对原图像进行缩放变换的程序。该程序首先装入一幅真彩色图像并显示该图像,然后对该图像进 行缩放变换,显示得到的结果。其中旋转中心位于图像中心,缩放系数为(0.707, 0.707),旋转角度为45度。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_COLOR);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Point2f center(img.cols / 2.0, img.rows / 2.0);
double angle = 45.0;
double scale = 0.707;
Mat rot_mat = getRotationMatrix2D(center, angle, scale);
Mat result;
warpAffine(img, result, rot_mat, img.size());
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
2. 使用OpenCV进行傅立叶变换和逆变换的演示
【问题描述】
使用OpenCV编写一个演示对原图像进行缩放变换的程序。该程序首先装入一幅真彩色图像并显示该图像,然后对该图像进 行缩放变换,显示得到的结果。其中旋转中心位于图像中心,缩放系数为(0.707, 0.707),旋转角度为45度。
【设计思路】
int main() {
// 装入一幅灰度图像
cv::Mat image = cv::imread("D:/tom.jpg", cv::IMREAD_GRAYSCALE);
// 显示原图像
cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
cv::imshow("Original Image", image);
cv::waitKey(0);
// 确保图像的尺寸是2的幂次方
int m = cv::getOptimalDFTSize(image.rows);
int n = cv::getOptimalDFTSize(image.cols);
cv::Mat padded;
cv::copyMakeBorder(image, padded, 0, m - image.rows, 0, n - image.cols, cv::BORDER_CONSTANT, cv::Scalar::all(0));
// 确保图像的数据类型是浮点型
padded.convertTo(padded, CV_32F);
// 进行傅立叶正变换
cv::Mat fourierTransform;
cv::dft(padded, fourierTransform, cv::DFT_COMPLEX_OUTPUT);
// 分离实部和虚部
cv::Mat planes[2];
cv::split(fourierTransform, planes);
cv::magnitude(planes[0], planes[1], planes[0]);
cv::Mat magnitudeImage = planes[0];
// 对数变换
magnitudeImage += cv::Scalar::all(1);
cv::log(magnitudeImage, magnitudeImage);
// 归一化
cv::normalize(magnitudeImage, magnitudeImage, 0, 1, cv::NORM_MINMAX);
// 显示傅立叶变换结果
cv::namedWindow("Fourier Transform", cv::WINDOW_NORMAL);
cv::imshow("Fourier Transform", magnitudeImage);
cv::waitKey(0);
// 进行傅立叶逆变换
cv::Mat inverseTransform;
cv::dft(fourierTransform, inverseTransform, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT);
// 显示傅立叶逆变换结果
cv::namedWindow("Inverse Transform", cv::WINDOW_NORMAL);
cv::imshow("Inverse Transform", inverseTransform);
cv::waitKey(0);
return 0;
}
【实验结果】
3. OpenCV中的FFTShift函数实现与应用
【问题描述】
请为OpenCV提供一个中心化函数FFTShift,该函数的函数原型为“Mat FFTShift(Mat X);”。
【设计思路】
Mat FFTShift(Mat X)
{
Mat Y;
int cx = X.cols / 2;
int cy = X.rows / 2;
Mat q1(X, Rect(0, 0, cx, cy));
Mat q2(X, Rect(cx, 0, cx, cy));
Mat q3(X, Rect(0, cy, cx, cy));
Mat q4(X, Rect(cx, cy, cx, cy));
q1.copyTo(Y(Rect(cx, cy, cx, cy)));
q2.copyTo(Y(Rect(0, cy, cx, cy)));
q3.copyTo(Y(Rect(cx, 0, cx, cy)));
q4.copyTo(Y(Rect(0, 0, cx, cy)));
return Y;
}
【实验结果】
在OpenCV中,我们可以通过以下步骤实现FFTShift函数:
1. 使用OpenCV进行中值模糊处理
【问题描述】
使用OpenCV编写一个程序,该程序对一幅彩色图像进行一次中值模糊,要求分别显示源图像和模糊化以后的图像。其中内核大小为5×5。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_COLOR);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat result;
medianBlur(img, result, 5);
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
2. 使用OpenCV进行Sobel锐化处理
【问题描述】
使用OpenCV编写一个程序,该程序对一幅灰度图像进行Sobel锐化,要求显示锐化以后的图像。其中内核大小为3×3,x和y方向均使用1阶差分。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
Sobel(img, grad_x, CV_16S, 1, 0, 3, 1, 0, BORDER_DEFAULT);
Sobel(img, grad_y, CV_16S, 0, 1, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
convertScaleAbs(grad_y, abs_grad_y);
Mat result;
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, result);
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
3. 使用OpenCV进行Laplace锐化处理
【问题描述】
使用OpenCV编写一个程序,该程序对一幅灰度图像进行Laplace锐化,要求显示锐化以后的图像。其中内核大小为3×3。
【设计思路】
导入所需的库,包括cv2和numpy。
读取灰度图像。
使用cv2.Laplacian()函数对图像进行Laplace锐化处理,设置内核大小为3×3。
显示原始图像和锐化后的图像。
保存锐化后的图像。
【关键程序】
int main()
{
Mat img = imread(“D:/tom.jpg”, IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow(“Original Image”, WINDOW_NORMAL);
imshow(“Original Image”, img);
Mat result;
Laplacian(img, result, CV_16S, 3, 1, 0, BORDER_DEFAULT);
convertScaleAbs(result, result);
namedWindow(“Result Image”, WINDOW_NORMAL);
imshow(“Result Image”, result);
waitKey(0);
return 0;
}
【实验结果】
4. 使用OpenCV进行2次腐蚀操作
【问题描述】
使用OpenCV编写一个程序,该程序使用大小为3的正方形模板(锚点位于模板中心)对源图像进行2次腐蚀操作,要求显示源图像和腐蚀以后的图像。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(1, 1));
Mat result;
erode(img, result, element, Point(-1, -1), 2);
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
5. 使用OpenCV进行2阶指数低通滤波
【问题描述】
使用OpenCV编写一个程序,该程序对一幅灰度图像进行一次2阶指数低通滤波,其中截止频率为20,要求分别显示源图像和滤波以后的图像。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat result;
double d0 = 20;
int n = 2;
int rows = img.rows;
int cols = img.cols;
Mat_<float> H(rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
float d = sqrt(pow(i - rows / 2, 2) + pow(j - cols / 2, 2));
H(i, j) = 1 / (1 + pow(d / d0, 2 * n));
}
}
Mat planes[] = { Mat_<float>(img), Mat::zeros(img.size(), CV_32F) };
Mat complex_img;
merge(planes, 2, complex_img);
dft(complex_img, complex_img);
split(complex_img, planes);
multiply(planes[0], H, planes[0]);
multiply(planes[1], H, planes[1]);
merge(planes, 2, complex_img);
idft(complex_img, complex_img);
split(complex_img, planes);
magnitude(planes[0], planes[1], result);
normalize(result, result, 0, 255, NORM_MINMAX);
result.convertTo(result, CV_8U);
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
6. 使用OpenCV进行2阶指数高通滤波
【问题描述】
使用OpenCV编写一个程序,该程序对一幅灰度图像进行一次2阶指数高通滤波,其中截止频率为45,要求分别显示源图像和滤波以后的图像。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat result;
double d0 = 45;
int n = 2;
int rows = img.rows;
int cols = img.cols;
Mat_<float> H(rows, cols);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
float d = sqrt(pow(i - rows / 2, 2) + pow(j - cols / 2, 2));
H(i, j) = 1 / (1 + pow(d0 / d, 2 * n));
}
}
Mat planes[] = { Mat_<float>(img), Mat::zeros(img.size(), CV_32F) };
Mat complex_img;
merge(planes, 2, complex_img);
dft(complex_img, complex_img);
split(complex_img, planes);
multiply(planes[0], H, planes[0]);
multiply(planes[1], H, planes[1]);
merge(planes, 2, complex_img);
idft(complex_img, complex_img);
split(complex_img, planes);
magnitude(planes[0], planes[1], result);
normalize(result, result, 0, 255, NORM_MINMAX);
result.convertTo(result, CV_8U);
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
1. 使用OpenCV进行灰度图像二值化变换
【问题描述】
使用OpenCV编写一个程序,该程序对一幅灰度图像进行二值化变换,要求分别显示源图像和二值化以后的图像。其中二值化阈值为127,高亮度改为255。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat result;
threshold(img, result, 127, 255, THRESH_BINARY);
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", result);
waitKey(0);
return 0;
}
【实验结果】
2. 使用OpenCV进行灰度图像Canny边缘检测
【问题描述】
使用OpenCV编写一个程序,该程序对一幅灰度图像进行Canny边缘检测,要求分别显示源图像和检测到的边缘。其中小阈值为50,大阈值为150,内核大小为3。
【设计思路】
int main()
{
Mat img = imread("D:/tom.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
std::cout << "Could not read the image: " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
Mat edges;
Canny(img, edges, 50, 150, 3);
namedWindow("Edges", WINDOW_NORMAL);
imshow("Edges", edges);
waitKey(0);
return 0;
}
【实验结果】
int main(int argc, char** argv)
{
// 读取彩色图像
Mat srcImage = imread("D:/tom.jpg");
if (srcImage.empty())
{
cout << "Could not open or find the image!\n" << endl;
return -1;
}
// 转换为灰度图像
Mat grayImage;
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
// 使用Canny算法检测边缘
Mat edgeImage;
Canny(grayImage, edgeImage, 100, 200);
// 复制出边缘像素
Mat resultImage;
srcImage.copyTo(resultImage, edgeImage);
resize(resultImage, resultImage, Size(500, 500));
// 显示结果图像
imshow("Result Image", resultImage);
waitKey(0);
return 0;
}
【实验结果】
int main()
{
Mat img = imread("D:/tom.jpg");
Mat templ = imread("D:/xm.jpg");
if (img.empty() || templ.empty())
{
std::cout << "Could not read the image(s): " << std::endl;
return 1;
}
namedWindow("Original Image", WINDOW_NORMAL);
imshow("Original Image", img);
namedWindow("Template Image", WINDOW_NORMAL);
imshow("Template Image", templ);
for (int i = 0; i < 6; i++)
{
Mat result;
matchTemplate(img, templ, result, i);
normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat());
double minVal, maxVal;
Point minLoc, maxLoc;
Point matchLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat());
if (i == 0 || i == 1)
{
matchLoc = minLoc;
}
else
{
matchLoc = maxLoc;
}
rectangle(img, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar(0, 0, 255), 2, 8, 0);
}
namedWindow("Result Image", WINDOW_NORMAL);
imshow("Result Image", img);
waitKey(0);
return 0;
}
【实验结果】