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


相关文章
|
1月前
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
38 2
C++入门12——详解多态1
|
1月前
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
79 1
|
1月前
|
存储 安全 编译器
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
23 0
|
1月前
|
自然语言处理 编译器 C语言
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
26 0
|
1月前
|
分布式计算 Java 编译器
【C++入门(下)】—— 我与C++的不解之缘(二)
【C++入门(下)】—— 我与C++的不解之缘(二)
|
1月前
|
编译器 Linux C语言
【C++入门(上)】—— 我与C++的不解之缘(一)
【C++入门(上)】—— 我与C++的不解之缘(一)
|
1月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
30 0
|
1月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
342 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
2月前
|
算法 计算机视觉
opencv图像形态学
图像形态学是一种基于数学形态学的图像处理技术,它主要用于分析和修改图像的形状和结构。
49 4
|
2月前
|
存储 计算机视觉
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
本文介绍了使用OpenCV进行图像读取、显示和存储的基本操作,以及如何绘制直线、圆形、矩形和文本等几何图形的方法。
Opencv的基本操作(一)图像的读取显示存储及几何图形的绘制
下一篇
无影云桌面