目录
通道
一幅图像,如果关闭了红色通道,那么图像就偏青色。如果关闭了绿色通道,那么图像就偏洋红色。如果关闭了蓝色通道,那么图像就偏黄色。
这个现象再次印证了反转色模型:红色对青色、绿色对洋红色、蓝色对黄色。
如果察看单个通道,发现每个通道都显示为一幅灰度图像(不能说是黑白图像)。某个通道的灰度图像中的明暗对应该通道色的明暗,从而表达出该色光在整体图像上的分布情况。由于通道共有3个,所以也就有了3幅灰度图像。
256种颜色对应256个数码(二进制数值)
也就是2^2 * 2^3 * 2^3 = 2^8 = 256。
8位的意思是:能够显示出来的颜色的数量有8位数
256色模式: 8 bits (B: 2 bits; G: 3 bits; R: 3 bits)。
图像像素的位深度
IPL_DEPTH_8U - 8位无符号整数
IPL_DEPTH_8S - 8位符号整数
IPL_DEPTH_16U - 16位无符号整数
IPL_DEPTH_16S - 16位符号整数
IPL_DEPTH_32S - 32位符号整数
IPL_DEPTH_32F - 单精度浮点数
IPL_DEPTH_64F - 双精度浮点数
CV1的用法,CV2 CV3 已经换为Mat
IplImage* img=cvCreateImage(cvGetSize(image), IPL_DEPTH_8U,3);//此处只是开辟内存
OpenCV 中Resize 和 cvPydown
Resize():将图像精确的转换为目标图像的尺寸,需要用到一些插值方法;
cvPyrdown会失真
canny边缘检测算法:
1.两个阈值是有区别的,高的那个阈值是将要提取轮廓的物体与背景区分开来,就像阈值分割的参数一样,是决定目标与背景对比度的;
低的阈值是用来平滑边缘的轮廓,有时高的阈值设置太大了,可能边缘轮廓不连续或者不够平滑,通过低阈值来平滑轮廓线,或者使不连续的部分连接起来。
Mat_和Mat区别
在读取矩阵元素时,以及获取矩阵某行的地址时,需要指定数据类型。这样首先需要不停地写“<uchar>”,让人感觉很繁琐,在繁琐和烦躁中容易犯错,如下面代码中的错误,用 at()获取矩阵元素时错误的使用了 double 类型。这种错误不是语法错误,因此在编译时编译器不会提醒。在程序运行时, at()函数获取到的不是期望的(i,j)位置处的元素,数据已经越界,但是运行时也未必会报错。这样的错误使得你的程序忽而看上去正常,忽而弹出“段错误”,特别是在代码规模很大时,难以查错。
如果使用 Mat_类,那么就可以在变量声明时确定元素的类型, 访问元素时不再需要指定元素类型,即使得代码简洁,又减少了出错的可能性。上面代码可以用 Mat_实现,实现代码如下面例程里的第二个双重 for 循环。
#include <iostream>
#include "opencv2/opencv.hpp"
#include<stdio.h>
using namespace std;
using namespace cv;
int main(int argc,char* argv[])
{
Mat M(600,800,CV_8UC1);
for(int i=0;i<M.rows;++i){
//获取指针时需要指定类型
uchar *p=M.ptr<uchar>(i);
for(int j=0;j<M.cols;++j){
double d1=(double)((i+j)%255);
//用at读像素时,需要指定类型
M.at<uchar>(i,j)=d1;
double d2=M.at<uchar>(i,j);
}
}
点操作(点算子)防止溢出
Mat类中的at方法作用:用于获取图像矩阵某点的值或改变某点的值。
对于单通道图像的使用方法:
image.at<uchar>(i,j) = 255;
对于RGB三通道图像的使用方法:
image.at<Vec3b>(i,j)[0] = 255;
image.at<Vec3b>(i,j)[1] = 255;
image.at<Vec3b>(i,j)[2] = 255;
Mat::at()取值或改变某点的像素值比较耗时,可以采用Mat的模板子类Mat_
实现对图像矩阵中某个值的获取和改变。
单通道的使用方法:
Mat_<uchar> img = image;
img(i,j) = 255;
三通道RGB的使用方法:
Mat_<Vec3b> img = image;
img(i,j)[0] = 255;
img(i,j)[1] = 255;
img(i,j)[2] = 255;
//在变量声明时,指定矩阵元素类型
Mat_<uchar> M1=(Mat_<uchar>&)M;
for(int i=0;i<M1.rows;++i)
{
//不需要指定元素类型,语言简洁
uchar *p=M1.ptr(i);
for(int j=0;j<M1.cols;++j){
double d1=(double)((i+j)%255);
//直接使用matlab风格的矩阵元素读写,简洁
M1(i,j)=d1;
double d2=M1(i,j);
}
}
return 0;
}
OpenCV3之——copyTo()函数的使用方法
定义和用法:
copyTo这个函数有两种定义方式,分别是:
void copyTo( OutputArray m ) const;
和
void copyTo( OutputArray m, InputArray mask ) const;
也就是参数可以是一张输出图像,或者一张输出图像和一个掩码图。
那么:
image.copyTo(imageROI);
就是把image这张图复制(copy to)到imageROI上。
image.copyTo(imageROI,mask);
则是不仅把image这张图复制(copy to)到mageROI上,且image对应mask中像素值为0的像素点都不会贴到imageROI上。
掩膜大小和要贴上去的图大小一致,不然内存报错。
saturate_cast在图像点操作(点算子)里面防止越界
pa.at<Vec3b>(i, j)[c] = saturate_cast<uchar>((g_nContrastValue*0.01)*pa.at<Vec3b>(i, j)[c] + g_nBrightValue);
加了saturate_cast
没加saturate_cast或者用了简单的强制类型转换
pa.at<Vec3b>(i, j)[c] = ((g_nContrastValue*0.01)*pa.at<Vec3b>(i, j)[c] + g_nBrightValue);
原理大致是这样:
if(data<0)
data=0;
else if(data>255)
data=255;