opencv初步学习01

在opencv中需要知道的一切图像皆为Mat

一、imread和imshows函数

代码:
#include <opencv2/opencv.hpp>
#include

using namespace cv;
using namespace std;

int main(int argc,char* argv){
    Mat src = imread("图像路径");//注意:这样的写法得到的图像永远都是彩色的
    //如若想要的是灰色的话,那么可以执行这段代码
    Mat src = imread("图像路径",IMREAD_GRAYSCALE);//加载出来的是灰度图像
    if(src.empty())
    {
        cout << "Failed load image"//当src图像加载失败的时候
    }
    //namedWindow("输出窗口名字",WINDOW_FREERATIO);这样来实现窗口大小显示的问题
    imshow("窗口的名称",src);//这里使用的是src是图像的对象,这个函数会创建一个新的窗口来显示对象
    waitKey(0);//0表示阻塞,1表示停留一毫秒
    destroyAllWindows();//表示关闭前面的所有已经打开的图像窗口,防止内存的泄露
    return 0;
}

注意:有个问题,就是关于opencv的imshows函数的实现,当图片的大小特别大的时候,会导致超出屏幕可显示范围,从而造成的是
图像的部分的无法显示。(imshow()函数实现的图像的大小的话,是autosize永远和图像的大小保持一致)
解决方案是:使用nameWindows来实现

二、cvtColor和imwrite

色彩空间转换函数-cvtColor
图像保存函数-imwrite
COLOR_BGR2GRAY = 6 彩色到灰度
COLOR_GRAY2BGR = 8 灰度到彩色
COLOR_BGR2HSV = 40 RGB到HSV
COLOR_HSV2BGR = 54 HSV到BGR

图像保存 - imwrite
第一个参数是图像保存路径
第二个参数是图像内存对象

代码案例:
quickDemo.h文件:
#include <opencv2/opencv.hpp>
using namespace cv;
class QuickDemo{
public:
void colorSpace_Demo(Mat& image);
};
quickDemo.cpp文件:
#include <quickDemo.h>

void QuickDemo::colorSpace_Demo(Mat& image)
{
    Mat grav,hsv;
    cvtColor(image,hsv,COLOR_BGR2HSV);
    cvtColor(image,gray,COLOR_BGR2GRAY);
    imshow("HSV",hsv);
    imshow("灰度",gray);
    imwrite("D:/hsv.png",hsv);//保存图片文件
    imwrite("D:/gray.png",gray);
}

三、C++中的Mat对象与创建

1、在opencv中的Mat数据类型的基本结构:
Mat基本结构分为:header(头部)和数据部分
数据部分:是所有像素值的集合
头部:数据类型的读取、通道数的获取

注意:每个Mat对象都会指向一个Data Block,当Mat对象进行赋值操作的时候,其实就是
指向同一个Data Block,只有进行克隆或者拷贝的时候,才会创建一个属于自己的Data Block,
然后这个Data Block里面存储的便是克隆或者拷贝之前的数据

//创建的Mat对象的方法:
//克隆
Mat m1 = src.clone();

//复制
Mat m2;
src.copyTo(m2);

//赋值
Mat m3 = src;

//创建空白图像
Mat m4 = Mat::zeros(src.size(),src.type());
Mat m5 = Mat::zeros(Size(512,512),CV_8UC3);
Mat m6 = Mat::ones(Size(512,512),CV_8UC3);

Mat kernel = (Mat(3,3) << 0,-1,0,-1,5,-1,0,-1,0);

代码案例:
void QuickDemo::mat_creation_demo(Mat& image)
{
Mat m1,m2;
m1 = image.clone();
image.copyTo(m2);

    //创建空白图像
    Mat m3 = Mat::zeros(Size(8,8),CV_8UC3);//CV_8UC1表示的是U表示的是无符号的,8表示8位的,C1表示的是只有一个通道
    m3 = 172;//这样子的写法的话,在cout m3的时候,就会出现八个像素值,每个像素值为 172,0,0    
    m3 = Scalar(127,127,127);//表示的是将三个通道的值都为127,每个像素的值为 127,127,127
    std::cout << "width(横向):" << m3.cols << "height:(纵向)" << m3.rows << "channels:(通道数)" << m3.channels() << std::endl;
    std::cout << m3 << std::endl;

}

注意:输出的Mat对象的横向的长度,其实是由两个因素所决定的,一是通道数,二是Size的值
例如:CV_8UC3,表示是3个通道,如果Size(8,8),表示的是横向为24,纵向为8。

注意:在使用Mat m3 = Mat::ones(Size(8,8),CV_8UC1);这样打印出来的是横向为8个1 纵向的话也是8个1
但是如果将通道数改为大于1,那么出现的情况是除了第一个通道数为1,其他的通道数为0,例如:一个像素表示为 1, 0, 0,

注意:对于CV_8UC3,表示的三个通道分别为B G R三个通道

部分代码案例:
Mat m3 = Mat::zeros(Size(400,400),CV_8UC3);
m3 = Scalar(255,0,0);
imshow("输出图像",m3);//这段代码输出的是一个窗口,窗口为400x400的纯蓝色图像,也就是说Scalar可以实现的是颜色的改变

Mat m4;
m4 = m3;
m4 = Scalar(0,255,0);
imshow("图像",m3);//这样输出的m3为绿色,因为这样实现的是,m4和m3进行的是赋值操作,所以m3和m4都是指向的是相同Data Block,所以修改m4,实际上修改的也是m3

四、图像像素的读写操作
1、C++中的像素遍历以及访问
(1)数组遍历
(2)指针方式遍历

代码案例:(通过数组遍历)
void QuickDemo::piex_visit_demo(Mat& image){
int w = image.cols;
int h = image.rows;
int dims = image.channels();
for(int row = 0;row < h;row++){
for(int col = 0;col < w;col++){
if(1 == dims){//灰度图像,只有一个通道
int pv = image.at(row,col);
image.at(row,col) = 255-pv;//进行图片的反向操作
}
if(3 == dims){//彩色图像,有三个通道
Vec3b bgr = image.at(row,col);//进行图片像素的反向操作
image.at(row,col)[0] = 255-bgr[0];
image.at(row,col)[1] = 255-bgr[1];
image.at(row,col)[2] = 255-bgr[2];
}
}
}
}

vec3b 表示三通道uchar
vec3s 表示三通道short(取之范围为-32768~32767)
vec3w 表示三通道ushort
vec3i 表示三通道int

代码案例:指针遍历实现
void QuickDemo::piex_visit_demo(Mat& image){
int w = image.cols;
int h = image.rows;
int dims = image.channels();
for(int row = 0;row < h;row++){
uchar* current_row = image.ptr(row);
for(int col = 0;col < w;col++){
if(1 == dims){//灰度图像,只有一个通道
int pv = *current_row;
*current_row ++ = 255 - pv;
}
if(3 == dims){//彩色图像,有三个通道
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
}
}
}
}

posted @ 2023-10-23 20:28  优秀还天籁  阅读(10)  评论(0编辑  收藏  举报