实验项目名称:图像基本操作
- 【实验摘要】
图像像素遍历是进行图像处理中常用的操作,表示访问图中每一个像素元素,本实验主要练习对图像像素的访问。
- 【实验原理】
Mat 数据类型
Mat 是 OpenCV 中新定义的类类型,用于存储图像数据,其数据类型灵活 多变,可以方便的用于存储各类图像。Mat 类是 OpenCV 里使用广泛的一个 类,其中最重要的一个作用就是作为存储图像的数据结构。Mat 类可以存储彩 色图像和灰度图像,并且数据类型可以是多种,如 8 位,16 位,32 位等的整型 和浮点型。另外,存储的图像不管是彩色的还是灰度图像,都是二维的矩阵, 但彩色图像每一像素的值都是一个向量。一般我们用 OpenCV 读取的灰度图像的数据类型为 uchar 类型的,而彩色图像的一个像素的数据类型为<Vec3b>类型 的,灰度图一个像素占用 1 个字节,而彩色图像一个像素 3 个字节。 下面列出 Mat 的部分用法(Mat image):
构造:double m[2][2]={ {1.0,2.0},{3.0,4.0}};Mat M(2,2,CV_32F,m)
Mat M(100,100,CV_32FC2,Scalar(1,3));
M.create(300,300,CV_8UC(15));产生 300*300 的 15 通道的矩阵。
Mat image(
240,320,CV_8U,Scalar(100));产生 240*320 的灰度图像,
灰度为 100。
Mat image=Mat::zeros(1000,1000,CV_32F);产生零矩阵。
Image.at<double>(i,j);获取矩阵第 i 行 j 列的值,值为 double 类型。
Image.row(1),image.col(3)分别表示获取矩阵第 1 行和第 3 列的值。
Image.rowRange(2,5),image.colRange(2,4);image.rowRange(2,5).colRange(2,4);
Image.size().height,image.size().width.
Image.cols,image.rows;2.1.2 像素的遍历(即访问)
要实现图像的处理,必须掌握如何访问图像中各像素元素,或者设置图像元素 值,创建图像。OpenCV 提供了几种图像像素的遍历方式,可根据实际需要选择 不同的访问方式进行。简要介绍如下:
(1)随机存取像素值
使用 Mat 中的公有成员 cols 和 rows 可以获得图像的调度和宽度,使用属性 channels 表示通道数,若为灰度图像,则值为 1,若为彩色图像,则值为 3。使用 成员函数 at(int y,int x)可以用来访问图像的元素,使用时必须指定数据类型,如 image.at<uchar>(j,i),对于彩色图像,每个像素由红、绿、蓝三通道构成,因此返 回的是一个向量,向量的每一元素为一个 unsigned char 变量,如 image.at<cv::Vec3b>(j,i)[chnnel]=value;
(2)采用指针对图像进行访问
上述随机遍历图像方便我们随意访问像素元素,但访问的效率很低,因此通常使用基 于指针的访问方式更快速。事实上,在 Mat 类中定义了一个指针变量存放图像数据的地 址,因此可以通过该变量访问图像数据,Mat 提供的函数 ptr<uchar>(i)可以获得第 i 行的首地址,从而可以实现对每一行的访问。
- 【实验过程及结果】
(一)实验过程
创建一个 VS 工程,完成系统环境的配置,实现图像的读取与显示;
1.新建一幅图像,使用随机访问(at 函数)和按行访问的方式
把读入的图像赋值给新建图像,同时显示两幅图像。
2.对图像进行二值化、反色等简单操作,并显示结果。
3.使用教师提供的添加噪声的程序,给图像添加盐噪声,编写程
序时注意区分单通道与三通道的处理。
- 实验结果
- 配置环境的步骤。
(1)第一步:配置环境变量
下载安装完成之后,我的电脑-属性-高级系统设置-系统变量-path;
将我们下载安装好的opencv文件夹打开,一直打开到opencv\\build\\x64\\vc15\\bin,复制该路径,粘贴到系统的环境变量中。
(2)第二步:在Visual Studio上配置OpenCV
1)打开visual studio 2022创建新项目,选择C++控制台应用。
2)点击顶部项目中“属性”。
3)编辑“VC++”目录中的“包含目录”,选择路径:
\\opencv\\build\\include,添加到我们的包含目录中。
- 编辑“VC++”目录中的“库目录”,选择路径:\\opencv\\build\\x64\\vc15\\lib,添加到我们的库目录中
- 编辑 “链接器”的“输入”中的“附加依赖项”。
- 复制文件夹:\\opencv\\build\\x64\\vc15\\lib中的opencv_world454d.lib文件,粘贴到附加依赖项中。
- 测试运行代码。
- 编写图像文件读取与图像显示的程序。
(1)二值化
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <iostream>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("d://yaya.jpg");
resize(img, img, Size(400, 400));//resize 为 400*400 的图像
imshow("ori", img);
cvtColor(img, img, CV_RGB2GRAY);
imshow("huidu",img);
Mat img1 = Mat::zeros(img.size(),img.type());
for (int i = 0; i < img.rows; i++)
{
for (int j = 0; j < img.cols; j++)
{
//at<类型>(i,j)进行操作,对于灰度图
float m=img.at<uchar>(i, j);//对于蓝色通道进行操作
//float g=img.at<Vec3b>(i, j)[1];//对于绿色通道进行操作
//float r=img.at<Vec3b>(i, j)[2];//对于红色通道进行操作
//变换
if (m<128) {
m = 0;
}
else {
m = 255;
}
img1.at<uchar>(i, j) = m;
}
}
imshow("result", img1);
waitKey(0);
return 0;
}
(2)反色
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <iostream>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("d://yaya.jpg");
resize(img, img, Size(400, 400));//resize 为 400*400 的图像