一、获取图像像素指针
方法一、
主要用到的函数是
Mat.ptr<uchar>(int i = 0)
它的作用是得到图像矩阵的的开始地址,可以跟据图像的储存的关系:
单通道图像:
行列 | column0 | column1 | … | columnn |
---|---|---|---|---|
row0 | piexl(0,0) | piexl(0,1) | … | piexl(0,n) |
row1 | piexl(1,0) | piexl(1,1) | … | piexl(1,n) |
⋮ | … | … | ⋱ | … |
rowm | piexl(m,0) | piexl(m,1) | … | piexl(m,n) |
RGB图像格式与上述相同,不过一个像素点由三个颜色分量表示。
//单通道图像为例:
const uchar * current = my_image.ptr<uchar>(row);//获取第row行地址指针
piexl_row_col = current[column];//得到第row行第column列像素的地址
//RGB图像操作:
//获取图像的Size与channel
int cols = src.cols * src.channels();
int offsetx = src.channels();
int rows = src.rows;
for (int row = 1; row < rows - 1; row++)
{
//等到行和列的地址
const uchar * previous = src.ptr<uchar>(row - 1);
const uchar * carrent = src.ptr<uchar>(row);
const uchar * next = src.ptr<uchar>(row + 1);
uchar * output = dst.ptr<uchar>(row);
for (int col = offsetx; col < cols; col++)
{
//掩膜处理
output[col] = saturate_cast<uchar>(carrent[col] * 5 - carrent[col - offsetx] - carrent[col + offsetx] - previous[col] - next[col]);
}
}
RGB图像操作例子中有一个常用的函数:
saturate_cast<uchar>
这个函数的功能是确保像素值在uchar类型数据允许范围之内
- saturate_cast(-100),函数返回0
- saturate_cast(280),函数返回255
- saturate_cast(100),函数返回100
二、掩膜操作
掩膜操作也可以成为卷积操作,就是把kernel(核)与图像卷积
如果把kernel定义为:
I(i,j)=5∗I(i,j)−[I(i,j−1)+I(i−1,j)+I(i+1,j)+I(i,j+1)]
我们把该式对应像素点的系数写成矩阵形式:
⎡⎣⎢0−10−15−10−10⎤⎦⎥
这个算子的作用是提高图像对比度,如果把该算子换成Laplace算子
⎡⎣⎢0101−41010⎤⎦⎥
就成了边缘检测。
卷积操作API
CV_EXPORTS_W void filter2D( InputArray src, OutputArray dst, int ddepth,
InputArray kernel, Point anchor = Point(-1,-1),
double delta = 0, int borderType = BORDER_DEFAULT );
用法:
//用opencv的API filter2D
Mat kernel = (Mat_<char>(3, 3) << 0, 1, 0, 1, -4, 1, 0, 1, 0);
filter2D(src, dst, -1, kernel);//此处-1为万能参数,也可以用src.depth()来代替-1
All demo:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char ** argv)
{
//读入图像
Mat src, dst;
src = imread("F:/Opencv/myimage/51CTO/4.jpg");
//判断图像是否读取错误
if (!src.data)
{
cout << "can not open the image ..." << endl;
return -1;
}
//初始化结果图像
dst = Mat::zeros(src.size(), src.type());
double t = getTickCount();
//掩膜操作
//获取图像的Size与channel
int cols = src.cols * src.channels();
int offsetx = src.channels();
int rows = src.rows;
for (int row = 1; row < rows - 1; row++)
{
//等到行和列的地址
const uchar * previous = src.ptr<uchar>(row - 1);
const uchar * carrent = src.ptr<uchar>(row);
const uchar * next = src.ptr<uchar>(row + 1);
uchar * output = dst.ptr<uchar>(row);
for (int col = offsetx; col < cols; col++)
{
//掩膜处理
output[col] = saturate_cast<uchar>(carrent[col] * 5 - carrent[col - offsetx] - carrent[col + offsetx] - previous[col] - next[col]);
}
}
cout << "myself function cost time:" << (getTickCount() - t) / getTickFrequency() << endl;
//display all image
namedWindow("Myself function", CV_WINDOW_AUTOSIZE);
imshow("Myself function", dst);
namedWindow("source image", CV_WINDOW_AUTOSIZE);
imshow("source image", src);
t = getTickCount();
//用opencv的API filter2D
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(src, dst, -1, kernel);//此处-1为万能参数,也可以用src.depth()来代替-1
namedWindow("OpenCV API", CV_WINDOW_AUTOSIZE);
imshow("OpenCV API", dst);
cout << "OpenCV API: " << (getTickCount() - t) / getTickFrequency() << endl;
waitKey(0);
return 0;
}
ps:
本例中还有一个实用的函数:
就是计算代码运行时间
传送门