访问像素值
cv::Mat类包含多种方法,可用来访问图像的各种属性:利用公共成员变量cols和rows可得到图像的列数和行数;利用cv::Mat的at(int y, int x)方法可以访问元素,其中x是列号,y是行号。在编译时必须明确方法返回值的类型,因为cv::Mat可以接受任何类型的元素,所以程序员需要指定返回值的预期类型。正因为如此,at方法被实现成一个模板方法。在调用at方法时,你必须指定图像元素的类型,例如:
image.at<uchar>(j, i)= 255;
彩色图像的每个像素对应三个部分:红色通道、绿色通道和蓝色通道,因此包含彩色图像的cv::Mat类会返回一个向量,向量中包含三个8位的数值。OpenCV为这样的短向量定义了一种类型,即cv::Vec3b。这个向量包含三个无符号字符(unsigned character)类型的数据。因此,访问彩色像素中元素的方法如下所示:
image.at<cv::Vec3b>(j, i)[channel]= value;
channel索引用来指明三个颜色通道中的一个。OpenCV存储通道数据的次序是蓝色、绿色和红色(因此蓝色是通道0)。你也可以直接使用短向量,方法如下所示:
image.at<cv::Vec3b>(j, i) = cv::Vec3b(255, 255, 255);
应用案例-添加噪声
//
// Created by zhongcheng Dai on 2023/5/9.
//
#include <random>
#include <iostream>
#include "opencv2/opencv.hpp"
void salt(cv::Mat image,int n){
//随机数生成器
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){
//灰度图像
image.at<uchar>(j,i) = 0;
}else if(image.type() == CV_8UC3){
image.at<cv::Vec3b>(j,i)[0] = 0;
image.at<cv::Vec3b>(j,i)[1] = 0;
image.at<cv::Vec3b>(j,i)[2] = 0;
}
}
}
int main(){
cv::Mat a = cv::imread("../../a.png",1);
cv::imshow("image",a);
salt(a,1000);
cv::imshow("image_salt",a);
cv::waitKey(0);
std::cout<<"test the main!"<<std::endl;
return 0;
}
cmake_minimum_required(VERSION 3.24)
project(salt_and_pepper)
find_package(OpenCV 4.6)
set(CMAKE_CXX_STANDARD_REQUIRED C11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
message("OpenCV: ${OpenCV_VERSION}")
add_executable(${
CMAKE_PROJECT_NAME})
target_sources(${
CMAKE_PROJECT_NAME} PRIVATE
main.cpp)
target_link_directories(${
CMAKE_PROJECT_NAME} PRIVATE
${
OpenCV_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${
CMAKE_PROJECT_NAME} PRIVATE
${
OpenCV_LIBS})
运行结果: