前言
开局一张图,内容全靠编。
访问像素值
函数 at()实现读去矩阵中的某个像素,或者对某个像素进行赋值操作。
例如:
uchar value = image.at<uchar>(i,j);//读出第 i 行第 j 列像素值
image.at<uchar>(i,j)=128; //将第 i 行第 j 列像素值设置为 128
在图像中加入椒盐噪声
椒盐噪声是一个专门的噪声类型,它随机选择一些像素,把它们的颜色替换成白色或黑色。如果通信时出错,部分像素的值在传输时丢失,就会产生这种噪声。这里只是随机选择一些像素,把它们设置为白色。
函数声明:
void salt(cv::Mat image, int n);
函数定义:
void salt(cv::Mat image, int n) {
// C++11 的随机数生成器
std::default_random_engine generator;
std::uniform_int_distribution<int>
randomRow(0, image.rows - 1);
std::uniform_int_distribution<int>
randomCol(0, image.cols - 1);
int i, j;
for (int k = 0; k < n; k++) {
// 随机生成图形位置
i = randomCol(generator);
j = randomRow(generator);
if (image.type() == CV_8UC1) { // 灰度图像
// 单通道 8 位图像
image.at<uchar>(j, i) = 255;
}
else if (image.type() == CV_8UC3) { // 彩色图像
// 3 通道图像
image.at<cv::Vec3b>(j, i)[0] = 255;
image.at<cv::Vec3b>(j, i)[1] = 255;
image.at<cv::Vec3b>(j, i)[2] = 255;
}
}
}
这个函数使用一个简单的循环,执行 n 次,每次都把随机选择的像素设置为 255。这里用随机数生成器生成像素的列 i 和行 j。请注意,这里使用了 type 方法来区分灰度图像和彩色图像。对于灰度图像,把单个的 8 位数值设置为 255;对于彩色图像,需要把三个主颜色通道都设置为255 才能得到一个白色像素。
测试代码:
#include <iostream>
#include <random>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
void salt(cv::Mat image, int n);
void salt(cv::Mat image, int n) {
// C++11 的随机数生成器
std::default_random_engine generator;
std::uniform_int_distribution<int>
randomRow(0, image.rows - 1);
std::uniform_int_distribution<int>
randomCol(0, image.cols - 1);
int i, j;
for (int k = 0; k < n; k++) {
// 随机生成图形位置
i = randomCol(generator);
j = randomRow(generator);
if (image.type() == CV_8UC1) { // 灰度图像
// 单通道 8 位图像
image.at<uchar>(j, i) = 255;
}
else if (image.type() == CV_8UC3) { // 彩色图像
// 3 通道图像
image.at<cv::Vec3b>(j, i)[0] = 255;
image.at<cv::Vec3b>(j, i)[1] = 255;
image.at<cv::Vec3b>(j, i)[2] = 255;
}
}
}
int main()
{
// 打开图像
cv::Mat image = cv::imread("test.bmp", 1);
if (image.empty()) { // 错误处理
// 未创建图像……
// 可能显示一个错误消息
// 并退出程序
std::cout << "no image!\n";
}
else
{
// 调用函数以添加噪声
salt(image, 3000);
// 显示结果
cv::namedWindow("Image");
cv::imshow("Image", image);
cv::waitKey(0); // 等待按键
}
system("pause");
return 0;
}
测试结果:
原图:
处理后图片:
OpenCV 存储通道数据的次序是蓝色(B)、绿色(G)和红色(R)
img.at<Vec3b>(row, col)[0] = 255; // 这是指修改B通道数据
img.at<Vec3b>(row, col)[1] = 255; // 这是指修改G通道数据
img.at<Vec3b>(row, col)[2] = 255; // 这是指修改R通道数据