sophiaechoz

大纲

1.视频文件摄像头的使用

2.一维直方图的绘制

3.二维直方图的绘制

4.直方图均衡化

 

1.视频文件摄像头的使用

(1)相关函数

开启摄像头设置:VideoCapture capture(0);    //开启摄像头数据(电脑自带)

保存视频设置:VideoWriter writer("D:/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);

读取视频:capture.read(frame);    //读取摄像头数据

保存视频:writer.write(frame);    //保存视频帧

关闭:

          capture.release();
          writer.release();

source code

(1)开启摄像头或视频设置

VideoCapture capture("F:/snip/VIDEOS/运动/VID_20210525_215712俯卧撑标准20个.mp4");    //开启摄像头数据(电脑自带)

(2)获取视频信息(如宽度,高度,总帧数,每秒播放的帧数)

    //视频信息
    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);          //1s有多少张图片
    std::cout << "frame width:" << frame_width <<std:: endl;
    std::cout << "frame_height:" << frame_height << std::endl;
    std::cout << "count:" << count << std::endl;
    std::cout << "fps:" << fps << std::endl;

(3)保存视频信息

//(1)视频编解码规则,
//(2)主要处理视频,相机的分辨率是否支持,由硬件决定的
//int xxx capture.set(CAP_PROP_FRAME_WIDTH);
//cou

VideoWriter writer("D:/test.mp4", capture.get(CAP_PROP_FOURCC), fps, Size(frame_width, frame_height), true);

(4)视频显示窗口,键盘退出,保存视频操作

    Mat frame;
    while (true)
    {
        capture.read(frame);    //读取摄像头数据
        flip(frame, frame, 1);  //镜像
        //chaneels_demo(frame);    //通道的分解
        //tracking_bar_demo(frame);
        if (frame.empty())      //如果没有图像,退出。
        {
            break;
        }
        //键盘响应
        namedWindow("frame", WINDOW_FREERATIO);    //自适应窗口
        imshow("frame", frame);
        writer.write(frame);    //保存视频帧
        //TODO:do something...
        int c = waitKey(3);    //3ms 一帧
        if (c == 27)    //ESC退出
        {
            break;
        }    
    }

(5)关闭视频,关闭保存

    capture.release();
    writer.release();

 

2.一维直方图的绘制

直方图的概念:

去除掉物理的地址信息,只保留像素大小。因而具有图像平移、旋转、缩放不变性等众多优点。

广泛应用于图像处理的各个领域。特别是灰度的阈值分割、基于颜色的图像检索以及图像分类等等。

                         

 

 

OpenCV只支持灰度图片的直方图

效果图:

函数:

直方图:calcHist(某个通道的矩阵引用, 图片的数量, 通道数, Mat(), 输出直方图矩阵, 输出维度, 等份个数,自变量的范围);

归一化:normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());  

source code

(1)通道分离

std::vector<Mat>bgr_plane;
split(image, bgr_plane);  //分离通道到容器 bgr_plane

(2)定义参数,步长,像素/样本的范围,定义三个矩阵去接收直方图的数据

    const int channels[1] = { 0 };   //通道的个数
    const int bins[1] = { 256 };     //直方图分割成多少个区间,就是bin的个数
    float hranges[2] = { 0,255 };   //像素取值范围在0-255,直方图分割成多少个区间
    const float* ranges[1] = { hranges };
    Mat b_hist;
    Mat g_hist;
    Mat r_hist;

(3)Calculate Blue,green,red chaneels histogram

             calcHist(某个通道的矩阵引用图片的数量通道数, Mat(), 输出直方图矩阵输出维度, 等份个数,自变量的范围);

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

  (4) 自己设计画布,划分最小区间

    int hist_w = 512;
    int hist_h = 400;
    //划分x轴的数据,通过之前定义的区间个数
    int bin_w = cvRound((double)hist_w / bins[0]);        //OpenCV 四舍五入的函数,把它分割成256分
    Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);  //创建与指定的图片的尺寸相同的画布

(5)归一化直方图数据,限定数据范围在0-histImage.rows 

    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());

(6)绘制直线

for (int i = 1; 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(0, 255, 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(0, 0, 255), 2, 8, 0);
    }

(7)显示直方图

    namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
    imshow("Histogram Demo", histImage);

source code

void QuickDemo::histogram_demo(Mat& image)     //图像直方图
{
    //三通道分离
    std::vector<Mat>bgr_plane;
    split(image, bgr_plane);  //分离通道到容器 bgr_plane
    //定义参数变量
    const int channels[1] = { 0 };   //通道的个数
    const int bins[1] = { 256 };     //直方图分割成多少个区间,就是bin的个数
    float hranges[2] = { 0,255 };   //像素取值范围在0-255,直方图分割成多少个区间
    const float* ranges[1] = { hranges };
    Mat b_hist;
    Mat g_hist;
    Mat r_hist;
    //calculate Blue,green,red chaneels histogram
    //直方图的结果存放到b_hist,g_hist,r_hist中,是一个256x1的列数组
    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;
    //划分x轴的数据,通过之前定义的区间个数
    int bin_w = cvRound((double)hist_w / bins[0]);        //OpenCV 四舍五入的函数,把它分割成256分
    Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);  //创建与指定的图片的尺寸相同的画布

    //归一化直方图数据(限定数据范围:0-histImage.rows 之间)
    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());
    //MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化
    //Mask :Mat()
    //-1 表达式数据类型和通道相同
    //NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围。
    
    //绘制直方图曲线
    //在x轴方向上沿着从左到右绘制直线。
    //数据可视化工作!!!
    for (int i = 1; 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(0, 255, 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(0, 0, 255), 2, 8, 0);
    }

    //显示直方图 
    namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
    imshow("Histogram Demo", histImage);
}

(3)二维直方图的绘制

        RGB转HSV,V通道不算

效果图:

                  

(1)转换颜色空间

Mat hsv, hs_hist;
    cvtColor(image, hsv, COLOR_BGR2HSV);

(2)设定直方图参数,步长,数据范围,通道个数

    int hbins = 30, sbins = 32;   //得到步长,也就是180,划分30,得到6的步长
    int hist_bins[] = { hbins,sbins };
    float h_range[] = { 0,180 };
    float s_range[] = { 0,256 };
    const float* hs_ranges[] = { h_range,s_range }; //参数的范围
    int hs_chaneels[] = { 0,1 };  //H,S

(3)直方图

calcHist(&hsv, 1, hs_chaneels, Mat(), hs_hist,2,hist_bins,hs_ranges,true,false);

(4)计算最大像素和最小像素

double maxVal = 0;
minMaxLoc(hs_hist, 0, &maxVal, 0, 0);

(5)自定义画布范围,创建图像

int scale = 10;    //缩放因子
    Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);
    for (int h = 0; h < hbins; h++)
    {
        for (int s = 0; s < sbins; s++)
        {
            float binval = hs_hist.at<float>(h, s);      //(z = f(x,y))
            int intensity = cvRound(binval * 255 / maxVal);   //取最接近整数的数,归一化
            rectangle(hist2d_image, Point(h * scale, s * scale),
                Point((h+1) * scale-1, (s+1) * scale-1),
                Scalar::all(intensity),-1);
        }
        //一维是线段,二维是框内数据
        applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);
        imshow("H-S Histogram", hist2d_image);
        imwrite("D:/test1.png", hist2d_image);
        
    }

(4)直方图均衡化

应用范围:用于图像增强(对比度),人脸检测,卫星遥感。均衡化的API只支持单通道

                 

 

函数:equalizeHist(原图,目标图);

 

source code

void QuickDemo::histogram_eq_demo(Mat &image)
{
    Mat gray;
    cvtColor(image, gray, COLOR_BGR2GRAY);
    imshow("灰度图像", gray);
    Mat dst;
    equalizeHist(gray, dst);
    imshow("直方图均衡化",dst);
}

 

Date:初心易得,始终难守    2021-12-24

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-24
  • 2021-05-18
  • 2021-12-05
  • 2021-06-20
猜你喜欢
  • 2022-01-23
  • 2021-12-21
  • 2021-12-04
  • 2021-07-06
  • 2021-10-27
  • 2022-01-23
相关资源
相似解决方案