图像基础
- 颜色通道
RGB 图像有4个默认通道:红色、绿色和蓝色各有一个通道,以及编辑图像的复合通道 - 彩色深度
8位色,每个像素所能显示的彩色数为2的8次方,256种颜色
16位增色 ,16位彩色,每个像素所能显示的彩色数为2的16次方,即65536种颜色。
24位真彩色,每个像素所能显示的彩色数为24位,即2的24次方,约1680万中颜色
32位真彩色,即在24位真彩色的图像基础上在加上一个表示图像的透明度信息的Alpha通道。 - CV_8UC3系列解读
cv_<bit_depth>(S|U|V)C<number_of_channels>
/*
1.bit_depth:像素点占用空间大小
2.S|U|F:
s:signed int -->有符号
U:unsigned int -->无符号
F:float -->单精度浮点数
3.number_of_channels
3.1 单通道图像,即为灰度图像
3.2 双通道图像
3.3 3通道图像
4.4 带Alpha通道的彩色图像 4通道图像
*/
读取图像
- Mat结构
OpenCV给我们提供了Mat类来存储矩阵类数据,包括向量,矩阵,图像的数据
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img(300,300,CV_8UC1);//注:300打印后数据太大
imshow("img");
waitKey(0);
return 0;
}
————————————————————————————————————
- Scalar它将各个通道的值构成一个整体,赋给具有相同通道数的矩阵元素,通俗点就是一个复合数据
Mat A{10,10,CV_8UC3,Scalar(1,2,3));
//CV_8UC3:8位存储的无符号3通道
//分别把每一个像素点颜色通道赋值为1 2 3
—————————————————————————————————————
- Mat的四种构造方式
Mat img(10,10,CV_8UC1);
//No.2
Mat img2(300,300,CV_8UC3,Scalar(0,255,0));
//N0.3
Mat img3 = img2.clone(); // 拷贝
//N0.4
Mat imag4;
imag3.copyTo(img4);
*imread函数读取图片
Mat imread(const String& filename,int flags = IMRED_COLOR);
/**********************************************************
* filename:文件路径
* flags :显示方式
***********************************************************/
enum ImreadModes
{
IMREAD_UNCHANGED = -1, //按原样返回加载的图片
IMREAD_GRAYSCALE = 0 //单通道灰度图片
IMREAD_COLOR = 1 //3通道BGR彩色的图片
IMREAD_ANYDEPTH = 2 //图像以任何可能的颜色格式读取
IMREAD_ANYCOLOR = 4 //图像以任何可能的颜色格式读取
IMREAD_LOAD_GDAL = 8 //gdal驱动程序加载映像
IMREAD_REDUCED_GRAYSCALE_2 = 16,
IMREAD_REDUCED_COLOR_2 = 17,
IMREAD_REDUCED_GRAYSCALE_4 = 32,
IMREAD_REDUCED_COLOR_4 = 33,
IMREAD_REDUCED_GRAYSCALE_8 = 64,
IMREAD_REDUCED_COLOR_8 = 65,
IMREAD_IGNORE_ORIENTATION = 128
}
像素读取
常用类型介绍
- uchar 类型
typedef unsigned uint;
typedef signed char shar;
typedef unsigned char uchar;
typedef unsigned short ushort;
- Vec系列
vec+数字+字母 :C++STL vector容器相似
数字:Vec的长度
字母:类型
b:uchar
s:short
w:ushort
i:int
f:float
d:double
数组方式读写
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
class ImgVisiPixel
{
public:
ImgVisitPixel(int type = IMGREAD_UNCHANGED):imag(imread("1.jpg",type))
{}
void Show(string wName)
{
imshow(wName,img);
moveWindow(wName,600,300);
waitKey(0);
}
void Visit_By_Array();
void Visit_ByPoint();
}
protected:
ImgVisitPixel* pImg = new ImgVisitPixel;
pImg->Show("原图");
};
int main()
{
ImgVisitPixel* pImg = new ImgVisitPixel;
pImge->show("原图");
pImge->Visit_By_Array();
pImge->show("负片");
}
void ImgVisitPixel::Visit_By_Array()
{
int dims = img.channels(); //得到图片通道数
for(int i = 0;i < img.rows;i++)
{
for(int j = 0;j < img.clos;j++)
{
//如果是单通道
if(dim == 1)
{
int pixel = img.at<uchar>(i,j);
img.at<uchar>(i,j) = 255- pixel; //负片处理
}
//3通道颜色获取图像
if(dims == 3)
{
Vec3b bgr = img.at<Vec3b>(i,j);
//负片处理
img.at<Vec3b>(i,j)[0] = 255-bgr[0];
img.at<Vec3b>(i,j)[1] = 255-bgr[1];
img.at<Vec3b>(i,j)[2] = 255-bgr[2];
}
}
}
}
void ImgVisitPixel::Visit_By_Point()
{
int dims = img.channels();
for(int i = 0;i < img.rows;i++)
{
uchar* current_row = img.ptr<uchar>(i);
for(int j = 0;j < img.clos;j++)
{
if(dims == 1)
{
int pixel = *current_row;
*current_row++=255-pixel; //做一个横向移动
}
if(dim == 3)
{
Vec3b bgr = img.at<Vec3b>(i,j);
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
}
}
}
}
注意
在读取到像素点的时候,做一些算数运算,一定要注意颜范围的问题,小心溢出,针对溢出,opencv提供一个转换防止溢出saturate_cast<要转换的类型>