多数内容都是摘抄自Opencv2计算机视觉编程手册,作者张静,这本书个人感觉非常好,希望可以帮到大家
/*
学习存取图像的内容,修改或者创建图像,所谓的内容和修改,其实就是对图像中的最基本元素像素进行各种操作。
学会遍历图像并且处理相应的像素,像素极多,必须学会高效处理像素的办法。
本质上讲,每一张图片本质上都是一个巨大的矩阵,矩阵的每一个元素代表一个像素值,举例来说,灰度图像的像素值由八位无符合值表示,取值范围是0-255 0代表黑丝,255代表白色
彩色图像中每一个像素需要三个这样的八位无符号数来表示三个颜色通道(红,绿,蓝),此种情况下,矩阵的元素是一个三元数
*/
/*存取像素的值*/
# include <opencv.hpp>
# include <iostream> //其实应该可以不用包括这个头文件 应该被包含在opencv中了
using namespace cv;
/*通过写一个函数来改变图像的像素,这个函数函数会在图像中加入椒盐噪点,椒盐噪点是一种特殊的噪点,随机的将部分像素设置为白色或者黑色
椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。
盐和胡椒噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等*/
void salt(Mat &image, int n)
{
for (int k = 0; k < n; k++)
{
//rand()随机数产生函数
int j = rand() % image.cols; //image.cols获取图像有多列像素
int i = rand() % image.rows; //image.rows获取图像有多行像素
if (image.channels() == 1) //image.channels()获取图像通道数 判断是灰色图像还是彩色图像
{
image.at<uchar>(i, j) = 255; //矩阵中元素的访问方法 : 灰度图:image.at<uchar>(行号,列号)= 255; 彩色图:image.at<cv::Vec3b>(行号, 例号) = cv::Vec3b(255, 255, 255);
}
else if (image.channels() == 3)
{
image.at<Vec3b>(i, j)[0] = 255; //C++区分大小写吗 ? 这里必须Vec3b V必须大写
image.at<Vec3b>(i, j)[1] = 255;
image.at<Vec3b>(i, j)[2] = 255;
}
}
}
int main()
{
Mat image;
image = imread("C:\\Users\\Administrator\\Pictures\\Test.jpg", IMREAD_UNCHANGED);//这里读取的图片一定要加上 后缀
salt(image, 30000);
namedWindow("椒盐噪点");
imshow("椒盐噪点", image);
waitKey(0);
}
/*
1:cv::Mat这一类 有若干成员函数可以获取图像的各种属性。公有成员变量rows和cols给出了图像的高和宽
2:成员函数at(int x, int y)可以用来存取图像元素,但是必须在编译时期知道图像的数据类型,因为CV::Mat可以存放认识数据类型的图像,所以采用
image.at<uchar>(i,j)函数模板来指定数据类型
3:写程序的时候一定要注意指定的数据类型一定要和矩阵中的数据类型一致,at方法本身是不会进行数据类型的转换的
4:对于彩色图像,每个像素由三个部分构成,红色通道,绿色通道,蓝色通道组成,所以一个包含彩色图像的cv::Mat会返回一个由三个字节组成的向量。opencv将此类向量定义为cv::Vec3b,
即由三个unsigned char组成的向量。所以存取彩色像素的函数模板为:image.at<Vec3b>(i,j)[channel] = value
类似的,opencv还有两元素或者四元素的向量类型即cv::Vec4b.
同样的,还有指向其他数据类型的向量类型,s代表short i代表int f代表float d代表double 所有的类型都是用cv::Vect<T,N>定义 T代表类型,N代表个数。
*/