[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)


目录
相关文章
|
16天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
40 6
|
3天前
|
C++
C++虚函数学习笔记
C++虚函数学习笔记
8 0
|
20天前
|
存储 人工智能 机器人
【C++面向对象】C++图书管理系统 (源码)【独一无二】
【C++面向对象】C++图书管理系统 (源码)【独一无二】
|
20天前
|
存储 人工智能 机器人
【C/C++】C++学籍信息管理系统(源码+报告)【独一无二】
【C/C++】C++学籍信息管理系统(源码+报告)【独一无二】
|
25天前
|
人工智能 机器人 测试技术
【C/C++】C语言 21点桌牌游戏 (源码) 【独一无二】
【C/C++】C语言 21点桌牌游戏 (源码) 【独一无二】
|
25天前
|
存储 人工智能 BI
【C++面向对象】C++银行卡管理系统(源码+论文)【独一无二】
【C++面向对象】C++银行卡管理系统(源码+论文)【独一无二】
|
26天前
|
XML JSON JavaScript
推荐一个比较好用的c++版本http协议库-cpp-httplib
推荐一个比较好用的c++版本http协议库-cpp-httplib
38 1
|
1月前
|
安全 编译器 C语言
【C++ 编译器 版本支持】深度解读C++ 版本以及编译器版本相关宏
【C++ 编译器 版本支持】深度解读C++ 版本以及编译器版本相关宏
54 0
|
1月前
|
SQL XML API
Qt C++ 模块 描述列表【从Qt 官网 6.5 版本翻译】
Qt C++ 模块 描述列表【从Qt 官网 6.5 版本翻译】
13 0
|
1月前
|
存储 缓存 调度
C++医院医学影像PACS系统源码 影像采集 DICOM影像
支持对财务及工作量信息进行统计; 支持对任意的检查类别,检查设备按照不同的检查项目(包括送检医生,送检;科室,检查类别,报告医生工作量等)进行任意时间段的统计; 可以按照检查类型,检查设备,检查项目,统计范围和日期范围等进行组合统计。
15 1