一、获取图像像素指针
CV Assert(mylmage.depth() == CV 8U);
CV_Assert()函数判断图像数据的类型是否为uchar类型,不满足则抛出异常。
Mat.ptr(int i=0)获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
Mat.ptr(int i=0)获取像素矩阵的指针,索引i表示第几行,从0开始计行数。
获取当前像素点P(row, col)的像素值p(row, col) =current[col]
像素范围处理
saturate_cast
saturate_cast ( -100 ),返回0
saturate_cast ( 288 ) ,返回255
saturate_cast ( 100 ) ,返回100
这个函数的功能是确保RGB值得范围在0~255之间
二、矩阵的掩膜操作
下面我们实现一个滤波器为下图的掩膜操作;
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
int main12(int arge, char** argv) {
//加载图像,使用默认加载方式
Mat src = imread("图片1.png");
if (src.empty())
{
printf("不能打开空图片");
return -1;
}
//显示原始图像
namedWindow("demo", CV_WINDOW_AUTOSIZE);
imshow("demo", src);
//显示转换后的图像
namedWindow("UOTPUT", CV_WINDOW_AUTOSIZE);
Mat output_image;
//开始转换,将原始图像转为灰度图
cvtColor(src, output_image, CV_RGB2HLS);
imshow("UOTPUT", output_image);
//保存图片
imwrite("./1.tif", output_image);
waitKey(0);
return 0;
}
int main() {
Mat src, det;
//读取图片
src = imread("图片1.png");
if (!src.data)
{
printf("不能打开空图片");
return -1;
}
//显示图片
namedWindow("INPUT", CV_WINDOW_AUTOSIZE);
imshow("INPUT", src);
//获取高度和宽度
int cols = (src.cols - 1) * src.channels();
int rows = src.rows;
int offsets = src.channels();
//定义一个与原始图像大小一致的全零矩阵
det = Mat::zeros(src.size(), src.type());
for (int row = 1; row < rows - 1; row++)
{
//获取像素的指针
//第一行的指针
const uchar* previous = src.ptr<uchar>(row - 1);
//第二行的指针
const uchar* current = src.ptr<uchar>(row);
//第三行的指针
const uchar* next = src.ptr<uchar>(row + 1);
uchar* output = det.ptr<uchar>(row);
for (int col = offsets; col < cols; col++)
{
output[col] = saturate_cast <uchar>(5 * current[col] - (current[col - offsets] + current[col + offsets] + previous[col] + next[col]));
}
}
//显示图片
namedWindow("OUTPUT", CV_WINDOW_AUTOSIZE);
imshow("OUTPUT", det);
waitKey(0);
return 0;
}
这里好多同学有疑问,为什么列宽为int cols = (src.cols - 1) * src.channels();,这里做一个简单的解释。
在opencv的处理中,三通道的图像矩阵如下:
一个像素需要多个矩阵元素来保存,矩阵中的列会包含多个子列,且子列数和通道数相等,就如上图所示。具体来说就是图像左上角的一个像素是包含三个小子列的,而这三个小子列就是我们RGB格式图片的三通道。