OpenCV4之C++入门详解 (中)

简介: OpenCV4之C++入门详解

2.10、图像像素的逻辑操作


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
};


quickdemo.cpp


void QuickDemo::bitwise_demo(Mat &image) {
  Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
  Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);
  //rectangle()函数第四个参数小于0表示填充,大于0表示绘制
  //rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), 2, LINE_8, 0);
  //rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), 2, LINE_8, 0);
  rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);
  rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
  imshow("m1", m1);
  imshow("m2", m2);
  Mat dst;
  //bitwise_and(m1, m2, dst);
  //bitwise_or(m1, m2, dst);
  //dst = ~image;  //也可以实现图像取反操作
  //bitwise_not(image, dst);  //当前图像取反操作
  bitwise_xor(m1, m2, dst);  //异或((非m1 与 m2) 或 (m1 与 非m2)),相当于 m1或m2,相交的部分(非(m1 与 m2))
  imshow("像素位操作", dst);
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/lena.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.bitwise_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.11、通道分离与合并


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
      void channels_demo(Mat &image);
};


quickdemo.cpp


void QuickDemo::channels_demo(Mat &image) {
  std::vector<Mat> mv;  //Mat数组
  split(image, mv);
  imshow("蓝色", mv[0]);
  imshow("绿色", mv[1]);
  imshow("红色", mv[2]);
  Mat dst;
  //mv[1] = 0;
  //mv[2] = 0;
  //merge(mv, dst);
  //imshow("蓝色", dst);
  //mv[0] = 0;
  //mv[2] = 0;
  //merge(mv, dst);
  //imshow("绿色", dst);
  mv[0] = 0;
  mv[1] = 0;
  merge(mv, dst);
  imshow("红色", dst);
  //from_to[]复制列表
  int from_to[] = { 0,2,1,1,2,0 };  //通道0复制到通道2,通道1复制到通道1,通道2复制到通道0
  //mixChannels(输入矩阵,输入矩阵数量,输出矩阵,输出矩阵数量,复制列表,复制列表中复制几次)
  mixChannels(&image, 1, &dst, 1, from_to, 3);
  imshow("通道混合", dst);
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/flower.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.channels_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.12、图像色彩空间转换


HSV颜色空间表


image.png


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
};


quickdemo.cpp


void QuickDemo::inrange_demo(Mat &image) {
  Mat hsv;
  cvtColor(image, hsv, COLOR_BGR2HSV);
  Mat mask;
  inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
  imshow("mask01", mask);
  Mat redback = Mat::zeros(image.size(), image.type());
  redback = Scalar(40, 40, 200);
  bitwise_not(mask, mask);  //像素逻辑运算,mask取反
  imshow("mask02", mask);
  //image.copyTo(拷贝到的图像,mask为1的部分拷贝为0的部分不拷贝)
  image.copyTo(redback, mask);  //将image拷贝到其他图像中
  imshow("roi区域提取", redback);
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.inrange_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.13、图像像素值统计


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
              void pixel_statistic_demo(Mat &image);
};


quickdemo.cpp


void QuickDemo::pixel_statistic_demo(Mat &image) {
  double minv, maxv;
  Point minLoc, maxLoc;
  Mat mean, stddev;
  std::vector<Mat> mv;
  split(image, mv);
  for (int i = 0; i < mv.size(); i++) {
    //第一个参数需要是单通道的图像,可以先把多通道分离;最后一个参数为mask
    minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
    std::cout << "No.channels: " << i << " min value: " << minv << " max value: " << maxv << std::endl;
    //第一个参数是单通道图像则计算一组均值、方差,如果是多通道图像,则同时计算多组均值、方差
    meanStdDev(mv[i], mean, stddev);
    std::cout << "means: " << mean << std::endl;
    std::cout << "stddev: " << stddev << std::endl;
  }
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.pixel_statistic_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.14、图像几何形状绘制,随机数与随机颜色


基本绘图


1 Point:
 2     Point pt;
 3     pt.x = 10;
 4     pt.y = 8;
 5     或者
 6     Point pt =  Point(10, 8);
 7  
 8 Scalar:
 9     Scalar( B, G, R )   //定义的RGB颜色值为:Blue,Green, Red
10     
11 line 绘直线:
12     line( img,   //输出图像
13         start,   //起始点
14         end,     //结束点
15         Scalar( 0, 0, 0 ),  //颜色
16         thickness=2,    //线条粗细
17         lineType=8 );   //线条类型
18  
19 ellipse 绘椭圆:
20     ellipse( img,   //输出图像
21            Point( w/2.0, w/2.0 ),   //中心为点 (w/2.0, w/2.0) 
22            Size( w/4.0, w/16.0 ),     //大小位于矩形 (w/4.0, w/16.0) 内
23            angle,    //旋转角度为 angle
24            0,
25            360,     //扩展的弧度从 0 度到 360 度
26            Scalar( 255, 0, 0 ),   //颜色
27            thickness,   //线条粗细
28            lineType );    //线条类型
29  
30 circle 绘圆:
31     circle( img,   //输出图像
32          center,    //圆心由点 center 定义
33          w/32.0,     /圆的半径为: w/32.0
34          Scalar( 0, 0, 255 ),   //颜色
35          thickness,   //线条粗细
36          lineType );   //线条类型
37          
38 rectangle 绘矩形:
39     rectangle( rook_image,
40            Point( 0, 7*w/8.0 ),
41            Point( w, w),    //矩形两个对角顶点为 Point( 0, 7*w/8.0 ) 和 Point( w, w)
42            Scalar( 0, 255, 255 ),
43            thickness = -1,
44            lineType = 8 );
45  
46 fillPoly 绘填充的多边形:
47     fillPoly( img,
48             ppt,   //多边形的顶点集为 ppt
49             npt,   //要绘制的多边形顶点数目为 npt
50             1,   //要绘制的多边形数量仅为 1
51             Scalar( 255, 255, 255 ),
52             lineType );


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
              void pixel_statistic_demo(Mat &image);
              void form_paint_random();
};


quickdemo.cpp


void QuickDemo::form_paint_random() {
  Mat image_line = Mat::zeros(512, 512, CV_8UC3);  //新建两个512*512的三通道矩阵
  Mat image_rect = Mat::zeros(512, 512, CV_8UC3);
  Rect rect;  //新建一个矩形对象
  RNG rng(0xFFFFFF);  //生成随机数的类RNG,随机数产生器,用数值0xFFFFFF来实例化一个RNG对象
  image_line.setTo(Scalar(0, 0, 0));  //将图像使用另一种颜色覆盖
  image_rect.setTo(Scalar(0, 0, 0));  //将图像使用另一种颜色覆盖
  for (int i = 0; i < 100000; i++) {
    int x1 = rng.uniform(0, 512);  //获取[0,512)的均匀分布的随机数
    int y1 = rng.uniform(0, 512);
    int x2 = rng.uniform(0, 512);
    int y2 = rng.uniform(0, 512);
    int b = rng.uniform(0, 256);
    int g = rng.uniform(0, 256);
    int r = rng.uniform(0, 256);
    //void line(绘制线段的图像,起点坐标,终点坐标,线段的颜色通过Scalar()定义,线段的宽度(线宽为负数时表示填充),线段的类型,坐标点小数点位数)
    line(image_line, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA, 0);  //线段的类型。可以取值LINE_8,LINE_4和LINE_AA,分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用LINE_AA(采用了高斯滤波)。
    imshow("image_line", image_line);
    rect.x = x1;  //定义矩形的左上顶点坐标及宽高
    rect.y = y1;
    rect.width = x2 - x1;
    rect.height = y2 - y1;
    rectangle(image_rect, rect, Scalar(b, g, r), 1, LINE_AA, 0);
    imshow("image_rect", image_rect);
    char c = waitKey(20);
    if (c == 27)
      break;
  }
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  //imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.form_paint_random();
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.15、多边形填充与绘制


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
              void pixel_statistic_demo(Mat &image);
              void form_paint_random();
              void polyline_drawing_demo();
};


quickdemo.cpp


void QuickDemo::polyline_drawing_demo() {
  Mat canvas01 = Mat::zeros(Size(512, 512), CV_8UC3);
  Mat canvas02 = Mat::zeros(Size(512, 512), CV_8UC3);
  Point p1(100, 100);
  Point p2(350, 100);
  Point p3(450, 280);
  Point p4(320, 450);
  Point p5(80, 400);
  std::vector<Point> pts;
  pts.push_back(p1);
  pts.push_back(p2);
  pts.push_back(p3);
  pts.push_back(p4);
  pts.push_back(p5);
  fillPoly(canvas01, pts, Scalar(255, 255, 0), 8, 0);
  //polylines(绘制所在图像,要绘制的顶点集合,图形是否闭合,线的颜色,线宽,线的类型)
  //polylines(canvas, pts, true, Scalar(0, 0, 255), 3, LINE_8, 0);  //不能设置线宽为负数进行填充
  polylines(canvas01, pts, true, Scalar(0, 0, 255), 3, LINE_AA, 0);  //使用LINE_AA抗锯齿
  std::vector<std::vector<Point>> contours;
  contours.push_back(pts);
  //drawContours(绘制所在的图像,绘制的点集的集合,绘制第几个点集-1表示全部绘制,线段颜色,线宽-1表示填充)
  drawContours(canvas02, contours, -1, Scalar(255, 0, 0), -1);
  imshow("多边形绘制01", canvas01);
  imshow("多边形绘制02", canvas02);
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  //imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.polyline_drawing_demo();
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.16、鼠标操作与响应


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
              void pixel_statistic_demo(Mat &image);
              void form_paint_random();
              void polyline_drawing_demo();
    void mouse_drawing_demo(Mat &image);
};


quickdemo.cpp


Point sp(-1, -1);  //起点
Point ep(-1, -1);  //终点
//新建一个temp矩阵保存原图像,没有绘制的
Mat temp;
static void on_draw(int event, int x, int y, int flags, void *userdata) {
  Mat image = *((Mat*)userdata);
  if (event == EVENT_LBUTTONDOWN) {
    sp.x = x;
    sp.y = y;
    std::cout << "start point: " << sp << std::endl;
  }
  else if (event == EVENT_LBUTTONUP) {
    ep.x = x;
    ep.y = y;
    int dx = ep.x - sp.x;
    int dy = ep.y - sp.y;
    if (dx > 0 && dy > 0) {
      Rect box(sp.x, sp.y, dx, dy);
      temp.copyTo(image);  //去除绘制目标区域的边框
      imshow("ROI区域", image(box));  //将绘制区域中的图像单独显示出来
      rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
      imshow("鼠标绘制", image);
      //ready for next drawing
      sp.x = -1;
      sp.y = -1;
    }
  }
  else if (event == EVENT_MOUSEMOVE) {
    if (sp.x > 0 && sp.y > 0) {
      ep.x = x;
      ep.y = y;
      int dx = ep.x - sp.x;
      int dy = ep.y - sp.y;
      if (dx > 0 && dy > 0) {
        Rect box(sp.x, sp.y, dx, dy);
        temp.copyTo(image);  //每次都重新加载没有绘制的原图,实现擦除过程中绘制的图形
        rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
        imshow("鼠标绘制", image);
      }
    }
  }
}
void QuickDemo::mouse_drawing_demo(Mat &image) {
  namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
  setMouseCallback("鼠标绘制", on_draw, (void*)(&image));
  imshow("鼠标绘制", image);
  temp = image.clone();  //将加载的原图克隆到临时矩阵temp中
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  //imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.mouse_drawing_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.17、图像像素类型转换与归一化


图像为什么要进行归一化:


归一化就是要把需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。首先归一化是为了后面数据处理的方便,其次是保证程序运行时收敛加快。归一化的具体作用是归纳统一样本的统计分布性。归一化在0-1之间是统计的概率分布,归一化在某个区间上是统计的坐标分布。归一化有同一、统一和合一的意思。


归一化的目的简而言之,是使得没有可比性的数据变得具有可比性,同时又保持相比较的两个数据之间的相对关系,如大小关系;或是为了作图,原来很难在一张图上作出来,归一化后就可以很方便的给出图上的相对位置等。


四种归一化方式:


其中的NORM_L2计算方式实例如下公式,其他归一化方式根据图片中的内容即可理解

2.0÷22+82+1020.152.0÷22+82+102≈0.15


image.png


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
              void pixel_statistic_demo(Mat &image);
              void form_paint_random();
              void polyline_drawing_demo();
    void mouse_drawing_demo(Mat &image);
              void norm_demo(Mat &image);
};


quickdemo.cpp


//image.type()返回的数值与类型对应关系,第一行为通道数,第一列为数据类型
+--------+----+----+----+----+------+------+------+------+
|        | C1 | C2 | C3 | C4 | C(5) | C(6) | C(7) | C(8) |
+--------+----+----+----+----+------+------+------+------+
| CV_8U  |  0 |  8 | 16 | 24 |   32 |   40 |   48 |   56 |
| CV_8S  |  1 |  9 | 17 | 25 |   33 |   41 |   49 |   57 |
| CV_16U |  2 | 10 | 18 | 26 |   34 |   42 |   50 |   58 |
| CV_16S |  3 | 11 | 19 | 27 |   35 |   43 |   51 |   59 |
| CV_32S |  4 | 12 | 20 | 28 |   36 |   44 |   52 |   60 |
| CV_32F |  5 | 13 | 21 | 29 |   37 |   45 |   53 |   61 |
| CV_64F |  6 | 14 | 22 | 30 |   38 |   46 |   54 |   62 |
+--------+----+----+----+----+------+------+------+------+
void QuickDemo::norm_demo(Mat &image) {
  Mat dst;
  std::cout << image.type() << std::endl;
  image.convertTo(image, CV_32F);  //将8UC3 Integer数据转换成32F float数据,以便用于后续归一化操作
  std::cout << image.type() << std::endl;
  //值归一化与范围归一化:值归一化L1,L2,MINMAX;范围归一化可以自己设置归一化范围如[0,255]
  //normalize(输入数组,输出数组,1用来规范值2规范范围下限,0值归一化其他范围归一化上限,归一化选择的数学公式类型)
  normalize(image, dst, 1.0, 0, NORM_MINMAX);  //转换为浮点数类型后必须进行归一化操作
  std::cout << dst.type() << std::endl;
  imshow("图像数据归一化前", image);
  imshow("图像数据归一化后", dst);
  //CV_8UC3, CV_32FC3
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.norm_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.18、图像放缩与插值


OpenCV图像放缩的五种插值算法:最近邻、双线性、双三次、基于像素区域关系、兰索斯插值。


1、最近邻:选取离目标点最近的点作为新的插入点;


2、双线性:由相邻的四像素(2 * 2)计算得出;


  • 原理公式及矩阵

image.png


  • 计算过程示意图

image.png


3、双三次:由相邻的4 * 4像素计算得出,公式类似于双线性插值;


4、基于像素区域关系:共分三种情况,图像放大时类似于双线性插值,图像缩小(x轴、y轴同时缩小)又分两种情况,此情况下可以避免波纹出现;


5、兰索斯插值:由相邻的8 * 8像素计算得出,公式类似于双线性


总结:


  • 速度比较:INTER_NEAREST(最近邻插值)>INTER_LINEAR(双线性插值)>INTER_CUBIC(三次样条插值)>INTER_AREA(区域插值)


  • OpenCV推荐:如果要缩小图像,通常推荐使用 INTER_AREA插值效果最好;而要放大图像,通常使用 INTER_CUBIC(速度较慢,但效果最好),或者使用 INTER_LINEAR(速度较快,效果还可以)。至于最近邻插值 INTER_NEAREST,一般不推荐使用


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
              void pixel_statistic_demo(Mat &image);
              void form_paint_random();
              void polyline_drawing_demo();
    void mouse_drawing_demo(Mat &image);
              void norm_demo(Mat &image);
              void resize_demo(Mat &image);
};


quickdemo.cpp


void QuickDemo::resize_demo(Mat &image) {
  Mat zoomin, zoomout;
  int h = image.rows;
  int w = image.cols;
  //resize(输入图像,输出图像,大小变换方法Size(),x方向缩放系数,y方向缩放系数,插值算法)
  //如果size有值,使用size做放缩插值,否则根据fx与fy卷积
  resize(image, zoomin, Size(w / 2, h / 2), 0, 0, INTER_LINEAR);
  imshow("zoomin", zoomin);
  resize(image, zoomout, Size(w * 1.5, h * 1.5), 0, 0, INTER_LINEAR);
  imshow("zoomout", zoomout);
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.resize_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果


image.png


2.19、图像翻转


quickopencv.h


#pragma once
#include<opencv2/opencv.hpp>
using namespace cv;
class QuickDemo {
  public:
    void colorSpace_Demo(Mat &image);
    void mat_creation_demo();
    void pixel_visit_demo(Mat &image);
    void operators_demo(Mat &image);
    void tracking_bar_demo(Mat &image);
    void key_demo(Mat &image);
    void color_style_demo(Mat &image);
    void bitwise_demo(Mat &image);
    void channels_demo(Mat &image);
    void inrange_demo(Mat &image);
              void pixel_statistic_demo(Mat &image);
              void form_paint_random();
              void polyline_drawing_demo();
    void mouse_drawing_demo(Mat &image);
              void norm_demo(Mat &image);
              void resize_demo(Mat &image);
              void flip_demo(Mat &image);
};


quickdemo.cpp


void QuickDemo::flip_demo(Mat &image) {
  Mat dst;
  flip(image, dst, 0);  //上下翻转
  imshow("图像上下翻转", dst);
  flip(image, dst, 1);  //左右翻转
  imshow("图像左右翻转", dst);
  flip(image, dst, -1);  //180°旋转
  imshow("图像180°翻转", dst);
}


test440.cpp


#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char**argv) {
  // imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
  // B,G,R
  Mat src = imread("D:/images/greenback.jpg");   //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
  if (src.empty()) {
    printf("could not load image...\n");
    return -1;
  }
  //namedWindow("输入窗口", WINDOW_FREERATIO);   //不管图片大小,都能进行调整,图像很小可以不使用这个函数
  imshow("输入窗口", src);                    //第一个参数为窗口名
  QuickDemo qd;
  qd.flip_demo(src);
  waitKey(0);                               //窗口停留时间,0为一直停留,数值为停留的毫秒数
  destroyAllWindows();                      //关闭所有打开的窗口
  return 0;
}


效果

image.png


相关文章
|
2月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
47 2
C++入门12——详解多态1
|
2月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
89 1
|
2月前
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
30 0
|
2月前
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
39 0
|
2月前
|
分布式计算 Java 编译器
【C++入门(下)】—— 我与C++的不解之缘(二)
【C++入门(下)】—— 我与C++的不解之缘(二)
|
2月前
|
编译器 Linux C语言
【C++入门(上)】—— 我与C++的不解之缘(一)
【C++入门(上)】—— 我与C++的不解之缘(一)
|
2月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
41 0
|
29天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
50 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
103 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
90 4