图像基础

  • 颜色通道
    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<要转换的类型>