[opencv学习笔记] jiazhigang 30讲源码C++版本(含Makefile)

简介: [opencv学习笔记] jiazhigang 30讲源码C++版本(含Makefile)

课程目录

002 图像色彩空间转换

  1. 色彩空间转换函数 cvtColor
    COLOR_BGR2GRAY = 6 彩色到灰度
    COLOR_GRAY2BGR = 8 灰度到彩色
    COLOR_BGR2HSV = 40 BGR到HSV
    COLOR_HSV2BGR = 54 HSV到BGR
  2. 图像保存 imwrite
    第一个参数是图像保存路径
    第二个参数是图像内存对象

003 图像对象的创建和赋值

C++中Mat对象与创建

Python中Numpy数组对象

004 图像像素的读写操作

C++中的像素遍历与访问

  • 数组遍历
  • 指针方式遍历

005 图像像素的算数操作

saturate_castit; T> (vlaue)

006 滚动条操作演示 - 调整图像亮度

007 滚动条操作演示 - 参数传递度

008 键盘响应操作

009 opencv自带颜色表操作

aplayColorMap(src, dst, COLORMAP)

  • src表示输入图像
  • dst表示输出图像
  • 匹配到的颜色LUT,Opencv支持13中颜色风格的查找表映射
    010 图像像素的逻辑操作
    011 通道分离与合并
    012 图像色彩空间转换
    色彩空间与色彩空间转换
  • RGB色彩空间
  • HSV色彩空间
  • YUV色彩空间
  • YCrCb色彩空间

API

  • 色彩空间转换API cvtColor
  • 提取指定色彩范围区域inRange
    013 图像像素值统计
    像素值统计
  • 最小
  • 最大
  • 均值
  • 标准方差

API

  • 最大值最小值minMaxLoc
  • 计算均值与标准方差meanStdDev
    014 图像集合形状绘制
    015 随机数与随机颜色
    016 多边形填充绘制
    017 鼠标操作与响应
    018 图像像素类型转换与归一化
    Opencv中提供了四中像素归一化方法
  • NORM_MINMAX
  • NORM_INF
  • NORM_L1
  • NORM_L2
    最常用的就是NORM_MINMAX归一化方法

相关API函数:

normalize {
InputArray src, //输入图像
InputOutputArray, dst //输出图像
double alpha = 1, //NORM_MINMAX时候低值
double beta = 0, //NORM_MINMAX时候高值
int norm_type = NORM_L2, //只有alpha
int dtype = -1, // 默认类型与src一致
InputArray mask = noArray(), //mask默认值为空
}

019 图像放缩与插值

图像插值

最常见的四种插值算法

  • INTER_NEAREST = 0
  • INTER_LINEAR = 1
  • INTER_CUBIC = 2
  • INTER_LANCZOS4 = 4
    相关的应用场景:
    几何变换、透视变换、插值计算新像素
    resize
    如果size有值,使用size做缩放插值,否则根据fx与fy卷积
    020 图像翻转
    021 图像旋转
    022 视频文件摄像头调用
    023 视频处理与保存
    024 图像直方图
    图像直方图官方解释:
    图像直方图是图像像素值的统计学特征、计算代价较小、具有图像平移、旋转、缩放不变等众多优点,广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割,基于颜色的图像检索以及图像分类、反向投影跟踪。常见的分类有:
  • 灰度直方图
  • 颜色直方图

Bins指直方图的大小范围,对于像素值取值在0-255之间的,最少有256个bin,此外还可以有16,32,48,128等,256除以bin的大小应该是整数倍。

openCV相关API

calcHist

025 二维直方图

026 直方图均衡化

027 图像卷积操作

028 高斯模糊

029 高斯双边模糊

030 案例:实时人脸检测

源码

quickdemo.cpp

#include <quickopencv.h>
void QuickDemo::colorSpace_Demo(Mat &image)
{
  Mat gray, hsv;
  cvtColor(image, hsv, COLOR_BGR2HSV);
  cvtColor(image, gray, COLOR_BGR2GRAY);
  imshow("HSV", hsv);
  imshow("GRAY", gray);
  imwrite("./hsv.jpg", hsv);
  imwrite("./gray.jpg", gray);
}
void QuickDemo::mat_creation_demo()
{
  // Mat m1, m2;
  // m1 = image.clone();
  // image.copyTo(m2);
  //创建空白图像
  Mat m3 = Mat::zeros(Size(512,512), CV_8UC3); //CV_8UC1 8位unsigned char 1通道
  // m3 = 127;
  m3 = Scalar(127, 127, 127);
  std::cout << "宽度 " << m3.cols << "高度 " << m3.rows << "通道数" << m3.channels() << std::endl; 
  std::cout << m3 << std::endl;
  imshow("创建图像", m3);
}
void QuickDemo::pixel_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 (dims == 1)  //灰度图像
      {
        int pv = image.at<uchar>(row, col);
        image.at<uchar>(row, col) = 255 - pv;
      }
      if (dims == 3) //彩色图像
      {
        Vec3b bgr = image.at<Vec3b>(row, col);
        image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
        image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
        image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
      }
    }
  }
  // // 基于指针访问
  // for (int row = 0; row < h; row++)
  // {
  //  uchar *current_row = image.ptr<uchar>(row);
  //  for (int col = 0; col < w; col++)
  //  {
  //    if (dims == 1)  //灰度图像
  //    {
  //      int pv = *current_row;
  //      *current_row++ = 255 - pv;
  //    }
  //    if (dims == 3) //彩色图像
  //    {
  //      *current_row++ = 255 - *current_row;
  //      *current_row++ = 255 - *current_row;
  //      *current_row++ = 255 - *current_row;
  //    }
  //  }
  // }  
  imshow("像素读写演示", image);
}
void QuickDemo::operators_demo(Mat &image)
{
  // Mat dst;
  // dst = image + Scalar(50, 50, 50);
  // dst = image - Scalar(50, 50, 50);
  // dst = image * Scalar(2, 2, 2);
  // dst = image / Scalar(2, 2, 2);
  Mat dst = Mat::zeros(image.size(), image.type());
  Mat m = Mat::zeros(image.size(), image.type());
  m = Scalar(5, 5, 5);
  // add(image, m, dst);
  // substract(image, m, dst);
  divide(image, m, dst);
  // multiply(image, m, dst);
  imshow("加法操作", dst);
}
static void on_lightness(int b, void *userdata)
{
  Mat image = *((Mat*)userdata);
  Mat dst = Mat::zeros(image.size(), image.type());
  Mat m = Mat::zeros(image.size(), image.type());
  addWeighted(image, 1.0, m, 0, b, dst);  
  imshow("亮度与对比度调整", dst);
}
static void on_contrast(int b, void *userdata)
{
  Mat image = *((Mat*)userdata);
  Mat dst = Mat::zeros(image.size(), image.type());
  Mat m = Mat::zeros(image.size(), image.type());
  double contrast = b / 200.0;
  addWeighted(image, contrast, m, 0.0, 0, dst); 
  imshow("亮度与对比度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat &image)
{
  namedWindow("亮度与对比度调整", WINDOW_AUTOSIZE);
  int lightness = 50;
  int max_value = 100;
  int contrast_value = 100;
  createTrackbar("Value Bar:", "亮度与对比度调整", &lightness, max_value, on_lightness, (void*)(&image));
  createTrackbar("Contrast Bar:", "亮度与对比度调整", &contrast_value, 200, on_contrast, (void*)(&image));
  on_lightness(50, &image);
}
void QuickDemo::key_demo(Mat &image)
{
  Mat dst = Mat::zeros(image.size(), image.type());;
  while (true)
  {
    int c = waitKey(100);
    if (c == 27)    // ESC 退出
    {
      break;
    }
    if (c == 49)    //将图像转换为灰度图像显示
    {
      std::cout << "you input key #1" << std::endl;
      cvtColor(image, dst, COLOR_BGR2GRAY);
    }
    imshow("键盘响应", dst);
  }
}
void QuickDemo::color_style_demo(Mat &image)
{
  int colormap[] = 
  {
      COLORMAP_AUTUMN,
      COLORMAP_BONE,
      COLORMAP_JET,
      COLORMAP_WINTER,
      COLORMAP_RAINBOW,
      COLORMAP_OCEAN,
      COLORMAP_SUMMER,
      COLORMAP_SPRING,
      COLORMAP_COOL,
      COLORMAP_PINK,
      COLORMAP_HOT,
      COLORMAP_PARULA,
      COLORMAP_MAGMA,
      COLORMAP_INFERNO,
      COLORMAP_PLASMA,
      COLORMAP_VIRIDIS,
      COLORMAP_CIVIDIS,
      COLORMAP_TWILIGHT,
  };
  Mat dst;
  int index = 0;
  while(true)
  {
    int c = waitKey(200);
    if (c == 27)    // ESC 退出
    {
      break;
    }
    applyColorMap(image, dst, colormap[index % 19]);
    index++;
    imshow("颜色风格", dst);
  }
}
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(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);
  // bitwise_not(image, dst);
  bitwise_xor(m1, m2, dst);
  imshow("像素位操作", dst);
}
void QuickDemo::channels_demo(Mat &image)
{
  std::vector<Mat> mv;
  split(image, mv);
  imshow("B", mv[0]);
  imshow("G", mv[1]);
  imshow("R", mv[2]);
  Mat dst;
  mv[1] = 0;
  mv[2] = 0;
  merge(mv ,dst);
  imshow("蓝色", dst);
}
void QuickDemo::inrang_demo(Mat &image)
{
  Mat hsv;
  cvtColor(image, hsv, COLOR_BGR2HSV);
  Mat mask;
  inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
  Mat redback = Mat::zeros(image.size(), image.type());
  redback = Scalar(80, 80, 80);
  bitwise_not(mask, mask);
  imshow("mask", mask);
  image.copyTo(redback, mask);
  imshow("rio区域提取", redback);
}
void QuickDemo::pixel_statistic_demo(Mat &image)
{
  double minv, maxv;
  Point minLoc, maxLoc;
  std::vector<Mat> mv;
  split(image, mv);
  for (int i=0; i<mv.size(); i++)
  {
    minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
    std::cout << "No.channel:" << i << " min value " << minv << " max vlaue " << maxv << std::endl;
  }
  Mat mean, stddev;
  meanStdDev(image, mean, stddev);
  std::cout << "means " << mean << "stddev " << stddev << std::endl;
}
void QuickDemo::drawing_demo(Mat &image)
{
  Rect rect;
  rect.x = 200;
  rect.y = 200;
  rect.width = 100;
  rect.height = 100;
  Mat bg = Mat::zeros(image.size(), image.type());
  rectangle(bg, rect, Scalar(0, 0, 255), 2, 8, 0);
  circle(bg, Point(350, 400), 15, Scalar(255, 255, 255), 2, 8 ,0);
  RotatedRect rrt;
  rrt.center = Point(200,200);
  rrt.size = Size(100,200);
  rrt.angle = 0.0;
  ellipse(image, rrt, Scalar(255,255,255), 2, 8);
  line(bg, Point(100, 100), Point(350,400), Scalar(255,255,255), 2, 8, 0);
  Mat dst;
  addWeighted(image, 0.7, bg, 0.3, 0, dst);
  imshow("绘制演示", dst);
}
void QuickDemo::random_drawing_demo()
{
  Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
  int w = canvas.cols;
  int h = canvas.rows;
  RNG rng(12345);
  while (true)
  {
    int c = waitKey(100);
    if (c == 27)  // 退出
    {
      break;
    }
    int x1 = rng.uniform(0, w);
    int y1 = rng.uniform(0, h);   
    int x2 = rng.uniform(0, w);
    int y2 = rng.uniform(0, h);
    // canvas = Scalar(0,0,0);
    line(canvas, Point(x1,y1), Point(x2,y2), \
      Scalar(rng.uniform(0,255), rng.uniform(0,255),rng.uniform(0,255)), \
      1, LINE_AA, 0);
    imshow("随机绘制演示", canvas);
  }
}
void QuickDemo::polyline_drawing_demo()
{
  Mat canvas = 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);
  // // 先用polylines绘制, 再用fillPoly填充
  // polylines(canvas, pts, true, Scalar(100,255,200), 2, 0);
  // fillPoly(canvas, pts, Scalar(255,255,255), 8, 0);
  std::vector<std::vector<Point>> contours;
  contours.push_back(pts);
  // 直接绘制并填充
  drawContours(canvas, contours, -1, Scalar(255, 0, 0),-1);
  imshow("多边形绘制", canvas);
}
/********************************************************/
Point sp(-1, -1);
Point ep(-1, -1);
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);
      imshow("ROI区域", image(box));            
      rectangle(image, box, Scalar(0,0,255), 2, 8, 0);
      imshow("鼠标绘制", image);
      // 为下次绘制做好准备
      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();
}
void QuickDemo::norm_demo(Mat &image)
{
  Mat dst;
  
  std::cout << image.type() << std::endl;   // 16 - CV_8UC3
  image.convertTo(image, CV_32F);
  std::cout << image.type() << std::endl;   // 21 -CV_32FC3
  normalize(image, dst, 1.0, 0, NORM_MINMAX);
  std::cout << dst.type() << std::endl;   
  imshow("图像数据归一化", dst);
}
void QuickDemo::resize_demo(Mat &image)
{
  Mat zoomin, zoomout;
  int h = image.rows;
  int w = image.cols;
  resize(image, zoomin, Size(w/2, h/2), 0, 0, INTER_LINEAR);
  imshow("zoomin", zoomin);
  resize(image, zoomout, Size(w*2, h*2), 0, 0, INTER_LINEAR);
  imshow("zoomax", zoomout);
}
void QuickDemo::flip_demo(Mat &image)
{
  Mat dst;
  // flip(image, dst, 0);   // 上下翻转
  // flip(image, dst, 1);   // 左右翻转
  flip(image, dst, 1);    // 180度旋转
  imshow("图像翻转", dst);
}
void QuickDemo::rotate_demo(Mat &image)
{
  Mat dst, M;
  int w = image.cols;
  int h = image.rows;
  M = getRotationMatrix2D(Point2f(w/2, h/2), 45, 1.0);
  
  double cos = abs(M.at<double>(0, 0));
  double sin = abs(M.at<double>(0, 1));
  int nw = cos*w + sin*h;
  int nh = sin*w + cos*h;
  M.at<double>(0,2) += (nw/2 - w/2);
  M.at<double>(1,2) += (nh/2 - h/2);
  warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(0,0,255));
  imshow("旋转演示", dst);
}
void QuickDemo::video_demo(Mat &image)
{
  VideoCapture capture("/home/b/Downloads/opencv_tutorial_data-master/images/01.mp4");
  int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
  int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
  int count = capture.get(CAP_PROP_FRAME_COUNT);
  double fps = capture.get(CAP_PROP_FPS);
  std::cout << "frame_width:" << frame_width << std::endl;
  std::cout << "frame_height:" << frame_height << std::endl;
  std::cout << "number of frames:" << count << std::endl;
  std::cout << "fps:" << fps << std::endl;
  VideoWriter writer("./test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);
  Mat frame;
  while (true)
  {
    capture.read(frame);
    if (frame.empty())
    {
      break;
    }
    imshow("frame", frame);
    writer.write(frame);
    int c = waitKey(10);
    if (c == 27) //退出
    {
      break;
    }
  }
  capture.release();
  writer.release();
}
void QuickDemo::show_histogram_demo(Mat &image)
{
  // 三通道分离
  std::vector<Mat> bgr_plane;
  split(image, bgr_plane);
  // 定义参数变量
  const int channels[1] = {0};
  const int bins[1] = {256};
  float hranges[2] = {0, 255};
  const float *ranges[1] = {hranges};
  Mat b_hist;
  Mat g_hist;
  Mat r_hist;
  // 计算B、G、R通道的直方图
  calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
  calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
  calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
  // 显示直方图
  int hist_w = 512;
  int hist_h = 400;
  int bin_w = cvRound((double)hist_w / bins[0]);
  Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
  // 归一化直方图数据
  normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
  normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
  normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
  // 绘制直方图曲线
  for (int i=0; i<bins[0]; i++)
  {
    line(histImage, Point(bin_w*(i-1), hist_h-cvRound(b_hist.at<float>(i-1))), \
      Point(bin_w*(i), hist_h-cvRound(b_hist.at<float>(i))), Scalar(255,0,0), 2, 8, 0);   
    line(histImage, Point(bin_w*(i-1), hist_h-cvRound(g_hist.at<float>(i-1))), \
      Point(bin_w*(i), hist_h-cvRound(g_hist.at<float>(i))), Scalar(255,0,0), 2, 8, 0);
    line(histImage, Point(bin_w*(i-1), hist_h-cvRound(r_hist.at<float>(i-1))), \
      Point(bin_w*(i), hist_h-cvRound(r_hist.at<float>(i))), Scalar(255,0,0), 2, 8, 0);   
  }
  // 显示直方图
  namedWindow("Histogram demo", WINDOW_AUTOSIZE);
  imshow("Histogram demo", histImage);
}
void QuickDemo::histogram_2d_demo(Mat &image)
{
}
void QuickDemo::histogram_eq_demo(Mat &image)
{
}
void QuickDemo::blur_demo(Mat &image)
{
  Mat dst;
  blur(image, dst, Size(3,3), Point(-1,-1));
  imshow("图像模糊", dst);
}
void QuickDemo::gaussain_blur_demo(Mat &image)
{
  Mat dst;
  GaussianBlur(image, dst, Size(3,3), 15);
  imshow("高斯模糊", dst);
}
void QuickDemo::bifilter_demo(Mat &image)
{
  Mat dst;
  bilateralFilter(image, dst, 0, 100, 10);
  imshow("高斯双边模糊", dst);  
}

quickopencv.h

#ifndef QUICKOPENCV_H__
#define QUICKOPENCV_H__
#include <opencv2/opencv.hpp>
using namespace cv;
class QuickDemo
{
public:
  // 02 图像色彩空间变换
  void colorSpace_Demo(Mat &image);
  // 03 图像对象的创建与赋值
  void mat_creation_demo();
  // 04 图像像素的读写操作
  void pixel_visit_demo(Mat &image);
  // 05 图像像素的算数操作
  void operators_demo(Mat &image);
  // 06/07 滚动条操作演示 - 调整图像亮度
  void tracking_bar_demo(Mat &image);
  // 08 键盘响应操作
  void key_demo(Mat &image);
  // 09 opencv自带颜色表操作
  void color_style_demo(Mat &image);
  // 10 图像像素的逻辑操作(位操作)
  void bitwise_demo(Mat &image);
  // 011 通道分离与合并
  void channels_demo(Mat &image);
  // 012 图像色彩空间转换
  void inrang_demo(Mat &image);
  // 013 图像像素值统计
  void pixel_statistic_demo(Mat &image);
  // 014 画基本图形
  void drawing_demo(Mat &image);
  // 015 随机数和随机颜色
  void random_drawing_demo();
  //016 多边形填充和绘制
  void polyline_drawing_demo();
  // 017 鼠标操作与响应, ROI在线提取
  void mouse_drawing_demo(Mat &image);
  // 018 图像像素类型转换与归一化
  void norm_demo(Mat &image);
  // 019 图像放缩与插值
  void resize_demo(Mat &image);
  // 020 图像翻转
  void flip_demo(Mat &image);
  
  // 021 图像旋转 任意角度旋转,并修改旋转后空白背景
  void rotate_demo(Mat &image);
  // 022 视频文件摄像头调用    023 视频处理与保存
  void video_demo(Mat &image);
  // 024 图像直方图
  void show_histogram_demo(Mat &image);
  
  // 025 二维直方图
  void histogram_2d_demo(Mat &image);
  // 026 直方图均衡化
  void histogram_eq_demo(Mat &image);
  // 027 图像卷积操作
  void blur_demo(Mat &image);
  // 028 高斯模糊
  void gaussain_blur_demo(Mat &image);
  // 029 高斯双边模糊
  void bifilter_demo(Mat &image);
  // 030 案例:实时人脸检测
};
#endif

test440.cpp

#include <opencv2/opencv.hpp>
#include <quickopencv.h>
#include <iostream>
using namespace cv;
using namespace std;
int main(void)
{
  Mat src = imread("./test.jpg");
  if (src.empty())
  {
    printf("cann't load image\n");
    return -1;
  }
  imshow("xxxx", src);
  QuickDemo qd;
  // qd.colorSpace_Demo(src);
  // qd.mat_creation_demo();
  // qd.pixel_visit_demo(src);
  // qd.operators_demo(src);
  // qd.tracking_bar_demo(src);
  // qd.key_demo(src);
  // qd.color_style_demo(src);
  // qd.bitwise_demo(src);
  // qd.channels_demo(src);
  // qd.inrang_demo(src);
  // qd.pixel_statistic_demo(src);
  // qd.drawing_demo(src);
  // qd.random_drawing_demo();
  // qd.polyline_drawing_demo();
  // qd.mouse_drawing_demo(src);
  // qd.norm_demo(src);
  // qd.resize_demo(src);
  // qd.flip_demo(src);
  // qd.rotate_demo(src);
  // qd.video_demo(src);
  // qd.show_histogram_demo(src);
  // qd.histogram_2d_demo();
  // qd.histogram_eq_demo(src);
  // qd.blur_demo(src);
  // qd.gaussain_blur_demo(src);
  qd.bifilter_demo(src);
  waitKey(0);
  destroyAllWindows();
}

Makefile

CXX = g++
LIB = $(shell pkg-config --libs opencv4)
INC += $(shell pkg-config --cflags opencv4)
INC += -I ./
CXXFLAGS = -g -std=c++11 -Wall
 
TARGET = main
 
SRC=$(wildcard ./*.cpp)
 
OBJ=$(patsubst %.cpp, %.o, $(SRC))
 
$(TARGET): $(OBJ)
  $(CXX) $(CXXFLAGS) -o $@ $^ $(LIB)
 
$(OBJ):%.o: %.cpp
  $(CXX) $(CXXFLAGS)  $(INC) -o $@ -c $< 
 
clean:
  rm -f *.o
  rm -f $(TARGET)


相关文章
|
1月前
|
计算机视觉
Opencv学习笔记(十二):图片腐蚀和膨胀操作
这篇文章介绍了图像腐蚀和膨胀的原理、作用以及使用OpenCV实现这些操作的代码示例,并深入解析了开运算和闭运算的概念及其在图像形态学处理中的应用。
113 1
Opencv学习笔记(十二):图片腐蚀和膨胀操作
|
1月前
|
计算机视觉 Python
Opencv学习笔记(二):如何将整个文件下的彩色图片全部转换为灰度图
使用OpenCV库将一个文件夹内的所有彩色图片批量转换为灰度图,并提供了相应的Python代码示例。
35 0
Opencv学习笔记(二):如何将整个文件下的彩色图片全部转换为灰度图
|
1月前
|
计算机视觉 Python
Opencv学习笔记(一):如何将得到的图片保存在指定目录以及如何将文件夹里所有图片以数组形式输出
这篇博客介绍了如何使用OpenCV库在Python中将图片保存到指定目录,以及如何将文件夹中的所有图片读取并以数组形式输出。
144 0
Opencv学习笔记(一):如何将得到的图片保存在指定目录以及如何将文件夹里所有图片以数组形式输出
|
1月前
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
85 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
1月前
|
算法 计算机视觉
Opencv学习笔记(六):cv2.resize函数的介绍
这篇文章介绍了OpenCV库中cv2.resize函数的使用方法,包括其参数、插值方式选择以及实际代码示例。
261 1
Opencv学习笔记(六):cv2.resize函数的介绍
|
1月前
|
计算机视觉
Opencv学习笔记(八):如何通过cv2读取视频和摄像头来进行人脸检测(jetson nano)
如何使用OpenCV库通过cv2模块读取视频和摄像头进行人脸检测,并提供了相应的代码示例。
84 1
|
1月前
|
计算机视觉
Opencv学习笔记(五):cv2.putText()和cv2.rectangle()详细理解
这篇文章详细介绍了OpenCV库中的`cv2.putText()`和`cv2.rectangle()`函数的使用方法,并通过一个实战例子展示了如何使用这些函数在图像上绘制文字和矩形框。
137 0
Opencv学习笔记(五):cv2.putText()和cv2.rectangle()详细理解
|
1月前
|
计算机视觉
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
这篇文章详细介绍了OpenCV库中的图像二值化函数`cv2.threshold`,包括二值化的概念、常见的阈值类型、函数的参数说明以及通过代码实例展示了如何应用该函数进行图像二值化处理,并展示了运行结果。
342 0
Opencv学习笔记(三):图像二值化函数cv2.threshold函数详解
|
1月前
|
编解码 计算机视觉 Python
Opencv学习笔记(九):通过CV2将摄像头视频流保存为视频文件
使用OpenCV库通过CV2将摄像头视频流保存为视频文件,包括定义视频编码格式、设置保存路径、通过write写入视频文件,并提供了相应的Python代码示例。
125 0
|
1月前
|
Linux 编译器 测试技术
【C++】CentOS环境搭建-快速升级G++版本
通过上述任一方法,您都可以在CentOS环境中高效地升级G++至所需的最新版本,进而利用C++的新特性,提升开发效率和代码质量。
162 64