opencv学习笔记 二 操作像素
2017-09-24 22:05
351 查看
第二章: 操作像素
2.1引言:
灰度图像像素由8位无符号数来表示,0表示黑色,255表示白色。
彩色图像(RGB)像素由三个8位的无符号数来表示,存储方式为三元数(B,G,R)
2.2存取像素值
Mat类有若干成员和成员函数来获取图像的属性:
成员cols和rows表示 宽和高(列和行)
成员函数 at<像素类型名称>(int i, int j)可以用来存取像素
image.at<uchar>(i,j); //灰度图像的像素,at后的数据类型一定要和image像素数据类型吻合
image.at<Vec3b>(i,j); //RGB图像的像素 Vec3b表示三个8位无符号整形组成的向量
image.at<Vec3b>(i,j)[channel]; //像素向量的第channel个元素
image.at<Vec3b>(i,j)[1]; //第二个
image.at<Vec3b>(i,j)[2]; //第三个
int Mat::channels(); //用来获得像素的通道数
cv::Mat_类可以更方便访问像素
cv::Mat_<uchar> image1=image; //用Mat_类定义带数据类型的图像数据,可以直接访问像素
image1(i,j) = 0;
2.3使用指针来遍历图像
uchar *data = image.ptr<uchar>(j); //获取第i行的指针
data[i] = 0; //表示第i行,第j列元素值置0,而不是第i行第j列像素置0(RGB图像每个像素有三个元素)
颜色缩减函数:
div = pow(2,n);
uchar mask = 0xFF<<n;
data[i] = (data[i]&mask)+div/2;
上个颜色缩减函数中,改变原图像数据,若不想修改原图像则可以用:image.copyTo(image1);或者:void reducecolor(const Mat &image, Mat &result, int div){result.creat(image.rows, image.cols, image.type());……}//检查result和image大小数据类型是否一致
高效遍历图像:
底层指针运算:
2.4使用迭代器遍历图像遍历器是一种特殊的类,专门用于遍历集合中的各个元素图像迭代器的声明:
Mat Iterator_<Vec3b> it ;
Mat_<Vec3b>::iterator;
常量迭代器:当前不会对Mat类实例进行修改
Mat ConstIterator_<Vec3b> it ;
Mat_<Vec3b>::const_iterator;
2.5 编写高效的图像遍历循环
2.6 遍历图像和邻域操作锐化滤波器灰度图像:
彩色图像:
filter2D滤波器首先定义Mat核矩阵
#include <opencv2/imgproc.hpp> //包含filter2D()函数
2.7进行简单的图像算数
void addWeighted(InputArray src1, double alpha, InputArray src2,
double beta, double gamma, OutputArray dst, int dtype = -1);
dst = src1*alpha + scr*beta + gamma//(按输入的原格式返回)
add(imageA, imageB, imageC); //imageC = imageA + imageB//(A和B的大小应该相同)
add(imageA, scalar(k), imageC); //imageC = imageA + k
scaleAdd(imageA, k, imageB, imageC); //imageC = imageA*k +imageB
m1*m2 //矩阵乘法
m1.inv() //矩阵求逆
m1.t() //矩阵求转置
2.8 定义感兴趣的区域(ROI)添加logo
Mat image = imread("D:/1.jpg", 0);
imshow("picture原图", image);
Mat logo = imread("D
94ea
:/2.jpg", 0);
Mat imageROI;
logo = logo(Rect(0, 0, 400,200));
imshow("picturelogo", logo);
imageROI = image(Rect(0, 0, logo.cols, logo.rows));
addWeighted(imageROI, 0.5, logo, 0.5, 0.0, imageROI);
imshow("picture叠加", imageROI);
waitKey(0);
也可以通过图像掩膜完成定义ROI的方法:
imageROI = image(Rect(100, 100, 300, 300)); //选择顶点(100,100)宽度和长度分别为300,300
imageROI = image(range(100, 400), range(100,400)); //ROI与原始图像共享数据区
创建原始图像的特定行:
Mat imageROI = image.rowRange(start, end);
Mat imageROI = image.colRange(start, end);
2.1引言:
灰度图像像素由8位无符号数来表示,0表示黑色,255表示白色。
彩色图像(RGB)像素由三个8位的无符号数来表示,存储方式为三元数(B,G,R)
2.2存取像素值
Mat类有若干成员和成员函数来获取图像的属性:
成员cols和rows表示 宽和高(列和行)
成员函数 at<像素类型名称>(int i, int j)可以用来存取像素
image.at<uchar>(i,j); //灰度图像的像素,at后的数据类型一定要和image像素数据类型吻合
image.at<Vec3b>(i,j); //RGB图像的像素 Vec3b表示三个8位无符号整形组成的向量
image.at<Vec3b>(i,j)[channel]; //像素向量的第channel个元素
image.at<Vec3b>(i,j)[1]; //第二个
image.at<Vec3b>(i,j)[2]; //第三个
int Mat::channels(); //用来获得像素的通道数
cv::Mat_类可以更方便访问像素
cv::Mat_<uchar> image1=image; //用Mat_类定义带数据类型的图像数据,可以直接访问像素
image1(i,j) = 0;
2.3使用指针来遍历图像
uchar *data = image.ptr<uchar>(j); //获取第i行的指针
data[i] = 0; //表示第i行,第j列元素值置0,而不是第i行第j列像素置0(RGB图像每个像素有三个元素)
颜色缩减函数:
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> using namespace cv; using namespace std; void colorReduce(Mat &image, int div) { int n1 = image.rows; int nc = image.cols*image.channels(); for (int i = 0;i < n1;i++) { uchar *data = image.ptr<uchar>(i); for (int j = 0;j < nc;j++) { data[j] = data[j] / div *div + div / 2; } } } int main(int argc, char** argv) { Mat image = imread("D:/1.jpg", 1); namedWindow("picture"); imshow("picture", image); colorReduce(image, 10); namedWindow("key"); imshow("key", image); waitKey(0); return 0; }image.step //表示行的字节数image.element//表示像素的字节数颜色缩减:
div = pow(2,n);
uchar mask = 0xFF<<n;
data[i] = (data[i]&mask)+div/2;
上个颜色缩减函数中,改变原图像数据,若不想修改原图像则可以用:image.copyTo(image1);或者:void reducecolor(const Mat &image, Mat &result, int div){result.creat(image.rows, image.cols, image.type());……}//检查result和image大小数据类型是否一致
高效遍历图像:
void colorReduce(Mat &image, int div) { int n1 = image.rows; int nc = image.cols*image.channels(); //image.isContinuous()判断image是否有额外的填补 //返回值为真,则image没有进行额外的填补,即图像在内存中是连续存储的; //可以用一层循环来实现;这种方式在处理若干个小图像有优势 if (image.isContinuous()) { nc = image.cols*image.cols; n1 = 1; //image.reshape(1, image.cols*image.rows); 也可以用这个 } for (int i = 0;i < n1;i++) { uchar *data = image.ptr<uchar>(i); for (int j = 0;j < nc;j++) { data[j] = data[j] / div *div + div / 2; } } }
底层指针运算:
void colorReduce(Mat &image, int div) { int n1 = image.rows; int nc = image.cols*image.channels(); uchar *data = image.data;//image.data可以用来获取当前内存块的首地址 for (int i = 0;i < n1;i++) { for(int j =0;j<nc;j++) { data[j] = data[j] / div *div + div / 2; } data+=image.step;//image.step表示每一行的宽度(包括补充值) } }
2.4使用迭代器遍历图像遍历器是一种特殊的类,专门用于遍历集合中的各个元素图像迭代器的声明:
Mat Iterator_<Vec3b> it ;
Mat_<Vec3b>::iterator;
void colorReduce(Mat &image, int div) { //cv::Mat iterator_<cv::Vec3b> it;//不好使 Mat_<Vec3b>::iterator it = image.begin<Vec3b>(); Mat_<Vec3b>::iterator itend = image.end<Vec3b>(); for (;it != itend;++it)//it加一,it调向下一个像素(非元素) { (*it)[0] = (*it)[0] / div*div + div / 2; (*it)[1] = (*it)[1] / div*div + div / 2; (*it)[2] = (*it)[2] / div*div + div / 2; } }
常量迭代器:当前不会对Mat类实例进行修改
Mat ConstIterator_<Vec3b> it ;
Mat_<Vec3b>::const_iterator;
2.5 编写高效的图像遍历循环
void colorReduce(Mat &image, int div) { int n1 = image.rows; int nc = image.cols; if (image.isContinuous())//分类效率高 { nc *= n1; n1 = 1; } int n = static_cast<int>(log(static_cast<double>(div)) / log(2.0));//位运算效率高 uchar mask = 0xFF << n; for (int j = 0;j < n1;++j) { uchar *data = image.ptr<uchar>(j); for (int i = 0;i < nc;++i) { *data++ = *data&mask + div / 2; *data++ = *data&mask + div / 2; *data++ = *data&mask + div / 2; } } }
2.6 遍历图像和邻域操作锐化滤波器灰度图像:
void sharpen(const Mat &image, Mat &output) { output.create(image.size(), image.type()); for (int i = 1;i < image.rows - 1;++i) { const uchar *previous = image.ptr<uchar>(i-1); const uchar *current = image.ptr<uchar>(i); const uchar *next = image.ptr<uchar>(i+1); uchar *result = output.ptr<uchar>(i); for (int j = 1;j < image.cols-1;++j) { result[j] = saturate_cast<uchar>// saturate_cast<uchar>用于数据截断到0~255 (5 * current[j] - previous[j] - next[j] - current[j - 1] - current[j + 1]); //*result++ = 5 * current[j] - previous[j] - next[j] - current[j - 1] - current[j + 1]; } } output.row(0).setTo(Scalar(0));//output.row(0)表示输出的第0行,setTo(Scalar(0)),置为0 output.row(output.rows-1).setTo(Scalar(0)); output.col(0).setTo(Scalar(0)); output.col(output.cols-1).setTo(Scalar(0)); }
彩色图像:
void sharpen3d(const Mat &image, Mat &output) { output.create(image.size(), image.type()); int nc = image.cols * 3; for (int i = 1;i < image.rows - 1;++i) { const uchar *previous = image.ptr<uchar>(i-1); const uchar *current = image.ptr<uchar>(i); const uchar *next = image.ptr<uchar>(i+1); uchar *result = output.ptr<uchar>(i); for (int j = 3;j < nc-3;++j)//也可以使用迭代器 { result[j] = saturate_cast<uchar>// saturate_cast<uchar>用于数据截断到0~255 (5 * current[j] - previous[j] - next[j] - current[j - 3] - current[j + 3]); //*result++ = 5 * current[j] - previous[j] - next[j] - current[j - 1] - current[j + 1]; } } output.row(0).setTo(Scalar(0, 0, 0));//output.row(0)表示输出的第0行,setTo(Scalar(0)),置为0 output.row(output.rows-1).setTo(Scalar(0, 0, 0)); output.col(0).setTo(Scalar(0, 0, 0)); output.col(output.cols-1).setTo(Scalar(0, 0, 0)); }
filter2D滤波器首先定义Mat核矩阵
#include <opencv2/imgproc.hpp> //包含filter2D()函数
void sharpen2D(const Mat &image, Mat &output) { Mat kernel(3, 3, CV_32F, Scalar(0));//定义核矩阵 kernel.at<double>(0, 1) = -1; kernel.at<double>(1, 0) = -1; kernel.at<double>(1, 1) = 5; kernel.at<double>(2, 1) = -1; kernel.at<double>(1, 2) = -1; filter2D(image, output, image.depth, kernel); }
2.7进行简单的图像算数
void addWeighted(InputArray src1, double alpha, InputArray src2,
double beta, double gamma, OutputArray dst, int dtype = -1);
dst = src1*alpha + scr*beta + gamma//(按输入的原格式返回)
add(imageA, imageB, imageC); //imageC = imageA + imageB//(A和B的大小应该相同)
add(imageA, scalar(k), imageC); //imageC = imageA + k
scaleAdd(imageA, k, imageB, imageC); //imageC = imageA*k +imageB
m1*m2 //矩阵乘法
m1.inv() //矩阵求逆
m1.t() //矩阵求转置
2.8 定义感兴趣的区域(ROI)添加logo
Mat image = imread("D:/1.jpg", 0);
imshow("picture原图", image);
Mat logo = imread("D
94ea
:/2.jpg", 0);
Mat imageROI;
logo = logo(Rect(0, 0, 400,200));
imshow("picturelogo", logo);
imageROI = image(Rect(0, 0, logo.cols, logo.rows));
addWeighted(imageROI, 0.5, logo, 0.5, 0.0, imageROI);
imshow("picture叠加", imageROI);
waitKey(0);
也可以通过图像掩膜完成定义ROI的方法:
imageROI = image(Rect(100, 100, 300, 300)); //选择顶点(100,100)宽度和长度分别为300,300
imageROI = image(range(100, 400), range(100,400)); //ROI与原始图像共享数据区
创建原始图像的特定行:
Mat imageROI = image.rowRange(start, end);
Mat imageROI = image.colRange(start, end);
相关文章推荐
- OpenCV学习笔记(1)——操作像素
- openCV学习笔记(四):图像遍历和像素操作
- OpenCV学习笔记(四十一)——再看基础数据结构core OpenCV学习笔记(四十二)——Mat数据操作之普通青年、文艺青年、暴力青年 OpenCV学习笔记(四十三)——存取像素值操作汇总co
- c# opencvsharp学习笔记(3)兴趣区域ROI,图像叠加,操作像素点
- OpenCV学习笔记——存取像素值操作汇总core
- OpenCV学习笔记二-操作像素
- 我的OpenCV学习笔记(三):利用操作像素完成简单的图像处理:加入椒盐噪声、图像翻转、改变对比度、图像锐化
- 【OpenCV学习笔记】一.操作像素
- Opencv学习笔记之二:操作像素
- 我的OpenCV学习笔记(二):操作每个像素
- 【opencv学习笔记.1】操作像素画圆
- OpenCv学习笔记(六)----图像空间缩减,OpenCv中的计时函数和OpenCv中操作图像单个像素点的方法
- 【OpenCV学习笔记】三、操作像素
- OpenCV学习笔记 存取像素值操作汇总core
- 【OpenCV学习笔记 005】 操作像素
- OpenCV学习笔记二:操作像素
- 图像的像素点操作【OpenCV学习笔记3】
- Opencv学习笔记(四)--图像处理平滑,锐化操作
- opencv学习笔记(3) 锐化图像 邻域操作 ROI
- 【OpenCV学习笔记】2.2基本操作及函数