OpenCV基础API函数五

本文介绍了OpenCV的基础API应用,包括VideoCapture的视频读取,HSV颜色空间转换实现图像抠图,以及cornerHarris和goodFeaturesToTrack进行角点检测,ORB关键点检测与匹配。此外,还展示了透视变换、背景分析和图像校正等实用技术。

OpenCV基础API函数一

OpenCV基础API函数二

OpenCV基础API函数三

OpenCV基础API函数四

VideoCapture 读取视频

VideoCapture是一个类 设置或获取VideoCapter属性 videoCapture.set()或者videoCapture.get()

例子:读取视频

void video()
{
    //1 代表读取设备上的第二个摄像头 0代表第一个摄像头
    VideoCapture videoCapture(1);
    //读取视频文件
    //VideoCapture videoCapture("F:\\Opencv\\opencv\\sources\\samples\\data\\vtest.avi");

    //设置摄像头的像素 宽
    videoCapture.set(CV_CAP_PROP_FRAME_WIDTH,8160);
    //设置摄像头的像素 高
    videoCapture.set(CAP_PROP_FRAME_HEIGHT,8160);
    // 获取摄像头的像素 高
    int h=videoCapture.get(CAP_PROP_FRAME_HEIGHT);
    // 获取摄像头的像素 宽
    int w=videoCapture.get(CAP_PROP_FRAME_WIDTH);
    //获取视频的帧数
    int fps = videoCapture.get(CAP_PROP_FPS);
    //获取总帧数
    int fps_count = videoCapture.get(CAP_PROP_FRAME_COUNT);
    cout << "h " << h << " w " << w  <<"fps "<<fps <<"fps_count"<<fps_count<< endl;

    char c;
    Mat src;
    namedWindow("视频", WINDOW_FREERATIO);
    while(true)
    {
        videoCapture.read(src);
        if (src.empty())
        {
            break;

        }
        imshow("视频", src);
       // 按'ESC'键退出
        c=waitKey(10);

        if(c==27)
        {
            break;
        }
    }
    videoCapture.release();
}

HSV 颜色空间转换—抠图

请添加图片描述

inRange addWeighted相关API函数请看OpenCV基础API函数一
例子:抠图
请添加图片描述

void imageMatting()
{
    //摄像头视频
    VideoCapture videoCapture(1);
    //文件视频
    VideoCapture videoCaptureFile("C:\\Users\\Jason\\Desktop\\01.mp4");
    if(!videoCapture.isOpened() || !videoCaptureFile.isOpened())
    {
        cout << "文件打开失败" << endl;
        return;
    }
    videoCapture.set(CAP_PROP_FPS, videoCaptureFile.get(CAP_PROP_FPS));
    namedWindow("frame", WINDOW_FREERATIO);
    namedWindow("frameFile", WINDOW_FREERATIO);
    namedWindow("mask", WINDOW_FREERATIO);
    namedWindow("result", WINDOW_FREERATIO);

    char c;
    Mat frame, frameFile, hsv,mask;
    Mat reault;
    while (true)
    {
        videoCapture.read(frame);
        videoCaptureFile.read(frameFile);
        if (frame.empty() || frameFile.empty())
        {
            return;
        }
        //把摄像头文件视频大小转换到和文件视频大小一样
        resize(frame, frame, Size(frameFile.cols, frameFile.rows));
        reault = Mat::zeros(frameFile.size(), frameFile.type());
        imshow("frame", frame);
        imshow("frameFile",frameFile);

        //转换到HSV色彩空间
        cvtColor(frameFile, hsv, COLOR_BGR2HSV);

        //获取HSV指定的色彩范围
        inRange(hsv,Scalar(35,43,46),Scalar(77,255,255),mask);
        mask = ~mask;
        //把文件视频里指定的人物拷贝到result里面
        imshow("mask", mask);
        frameFile.copyTo(reault, mask);
        //两幅图片相加
        addWeighted(frame, 0.5, reault, 1, 0, reault);
        imshow("result", reault);

        c = waitKey(1);
        if (c == 27)
        {
            break;
        }
    }
}

calcBackProject 直方图反射投影 寻找目标物体

void calcBackProject( const Mat* images, int nimages,
                                 const int* channels, InputArray hist,
                                 OutputArray backProject, const float** ranges,
                                 double scale = 1, bool uniform = true );
返回值:空
images:输入的图片
ninages:图片的数量
hist:模板直方图
backProject:结果图像
ranges:每个维度直方图的取值范围
scale:是否缩放
uniform:是否归一化

例子:根据模板直方图,获取目标物体
在这里插入图片描述

void histReflect(Mat &src, Mat &srcModel)
{
    Mat src_hsv, model_hsv, model_hist;
    cvtColor(src, src_hsv, COLOR_BGR2HSV);
    cvtColor(srcModel, model_hsv, COLOR_BGR2HSV);
    int channles[] = {0, 1, 2};
    int h_histSize = 16;
    int s_histSize = 16;
    int v_histSize = 16;
    int histSize[] = {h_histSize, s_histSize, v_histSize};
    float h_range[] = {0, 180};
    float s_range[] = {0, 255};
    float v_range[] = {0, 255};
    const float *ranges[] = {h_range, s_range, v_range};
    //获取直方图
    calcHist(&model_hsv, 1, channles, Mat(), model_hist, 2, histSize, ranges);
    //直方图归一化
    normalize(model_hsv, model_hsv, 0, 255, NORM_MINMAX);
    Mat backProject;
    //直方图反射投影
    calcBackProject(&src_hsv, 1, channles, model_hist, backProject, ranges);
    imshow("直方图反射投影", backProject);
}

cornerHarris goodFeaturesToTrack 角点检测

void cornerHarris( InputArray src, OutputArray dst, int blockSize,
                                int ksize, double k,
                                int borderType = BORDER_DEFAULT );
返回值:空
src:输入的8bit灰度图像
dst:输出的角点检测的图像,类型是CV_32FC1 大小和src一样
blockSize:角点检测的邻域大小
ksize:sobel算子的窗口大小
k:Harris算法系数通常取 0.04---0.06
borderType :边缘填充方式

shi-tomasi角点检测算法性能高于Harris算法

void goodFeaturesToTrack( InputArray image, OutputArray corners,
                                     int maxCorners, double qualityLevel, double minDistance,
                                     InputArray mask = noArray(), int blockSize = 3,
                                     bool useHarrisDetector = false, double k = 0.04 );

返回值:空
image:输入的8bit灰度图像
corners:角点的坐标 类型为vector<Point2f>
qualityLevel:角点的质量水平,大于这个值得角点被保留,小于这个值得角点舍弃
minDistance:两个角点的最小距离,小于这个值得角点舍弃
mask:图像掩码;计算图像的那个部分,若要计算全部 mask==Mat()
blockSize:角点检测的邻域大小
useHarrisDetector:是否使用Harris进行角点检测,
k:Harris角点算法的系数通常取 0.04---0.06

例子:发现角点
在这里插入图片描述

void harrisAngularPoint(Mat &src)
{
    Mat gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    Mat dst;
    cornerHarris(gray, dst, 10, 3, 0.04);
    normalize(dst, dst, 0, 255, NORM_MINMAX);
    convertScaleAbs(dst, dst);

    for (int row = 0; row < src.rows; ++row)
    {

       for(int col=0;col<src.cols;col++)
       {
           int value = dst.at<uchar>(row, col);
           if(value>100)
           {
               circle(src, Point(col, row), 3, Scalar(255, 0, 0),-1);
           }
       }
    }
    namedWindow("结果", WINDOW_FREERATIO);
    imshow("结果", src);

	//shi-tomasi角点检测的效率要高于Harris角点检测
    vector<Point2f> corners;
    goodFeaturesToTrack(gray, corners, 500, 0.01, 3, Mat(), 3, false);
    for (int row = 0; row < corners.size(); ++row)
    {
        circle(src, corners[row], 3, Scalar(255, 0, 0), -1);
    }
    namedWindow("结果2", WINDOW_FREERATIO);
    imshow("结果2", src);

createBackgroundSubtractorMOG2 背景分析

请添加图片描述

//指针类型
//第一个参数   取多少帧进行计算背景
//第二个参数阈值
//第三个参数   是否分析阴影面积
Ptr<BackgroundSubtractorMOG2> bb = createBackgroundSubtractorMOG2(500, 32, false);

void myBackGroundExtract(Mat &src)
{
    Mat mask, back,binary;

    //应用此图像并获得Mask图像
    bb->apply(src, mask, -1);
    //获取背景
    bb->getBackgroundImage(back);
    namedWindow("mask",WINDOW_FREERATIO);
    namedWindow("background",WINDOW_FREERATIO);
    imshow("mask", mask);
    imshow("background", back);

    GaussianBlur(mask,mask,Size(0,0),3);
    threshold(mask,binary,0,255,THRESH_BINARY|cv::THRESH_OTSU);
    namedWindow("二值",WINDOW_FREERATIO);
    imshow("二值", binary);
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
//    发现轮廓
    findContours(binary,contours,hierarchy,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);
    for (int i = 0; i < contours.size(); ++i)
    {
        double area= contourArea(contours[i],false);
        if(area>100)
        {
            Rect box= boundingRect(contours[i]);
            rectangle(src,box,Scalar(0,0,255),2);
        }
    }
    namedWindow("src",WINDOW_FREERATIO);
    imshow("src", src);


}

ORB 关键点检测

 //创建ORB
 auto orb = ORB::create();
 static Ptr<ORB> create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8, int edgeThreshold=31,
        int firstLevel=0, int WTA_K=2, int scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20);
返回值:指针类型的ORB
nfeatures:特征点的数量
scaleFactor:每层金字塔图像抽取比例  应大于1 当scaleFactor==2时表示经典的金字塔图像,即下一层的图像像素数比上一层像素数少四倍,,但太大的比因子会降低特征的匹配分数
nlevels;金字塔的层数
edgeThreshold:图像边界的阈值,不会被匹配
firstLevel:金字塔的第一层,需要放置原图
WTA_K:用于产生BIREF描述子的点对的个数,一般为2个,也可以设置为3个或4个,那么这时候描述子之间的距离计算就不能用汉明距离了,而是应该用一个变种。OpenCV中,如果设置WET_K = 2,则选用点对就只有2个点,匹配的时候距离参数选择NORM_HAMMING,如果WET_K设置为3或4,则BIREF描述子会选择3个或4个点,那么后面匹配的时候应该选择的距离参数为NORM_HAMMING2。
scoreType:用于对特征点进行排序的算法,你可以选择HARRIS_SCORE,也可以选择FAST_SCORE,但是它也只是比前者快一点点而已。
patchSize :用于计算BIREF描述子的特征点邻域大小。
virtual void detect( InputArray image,
                                 CV_OUT std::vector<KeyPoint>& keypoints,
                                 InputArray mask=noArray() );
返回值:空
image:原图像
keypoints:特征点集合
mask:指定在何处查找关键点的掩码 Mat()表示全局查找

例子: 角点检测

在这里插入图片描述

void myORB(Mat &src)
{
    Mat dst;
    //创建ORB处理类
    auto orb=ORB::create(500);
    //关键点集合
    vector<KeyPoint> keyPoint;
    //处理关键点
    orb->detect(src,keyPoint);

    //绘制关键点
    drawKeypoints(src,keyPoint, dst,Scalar::all(-1));
    for (int i = 0; i < keyPoint.size(); ++i)
    {
        circle(src,keyPoint.at(i).pt,3,Scalar(0,0,255),1);
    }
    namedWindow("ORB角点检测",WINDOW_FREERATIO);
    imshow("ORB角点检测",src);
}

ORB 匹配

描述子

virtual void compute( InputArray image,
                                  CV_OUT CV_IN_OUT std::vector<KeyPoint>& keypoints,
                                  OutputArray descriptors );
image:原始图片
keypoints:关键点
descriptors:描述子 ORB的描述子是32位的2进制类型

创建匹配模式BFMatcher

static Ptr<BFMatcher> create( int normType=NORM_L2, bool crossCheck=false ) ;
返回值:指针类型 Ptr<BFMatcher>
normTyoe:匹配类型  NORM_L1, NORM_L2标准适合SIFT 和SURF;NORM_HAMMING标准适合ORB描述子,但是如果ORB的WTA_K=3或者WTA_K=4需要使用NORM_HAMMING2标准
crossCheck:交叉校验 当crossCheck=false 是标准模式
void match( InputArray queryDescriptors, InputArray trainDescriptors,
                CV_OUT std::vector<DMatch>& matches, InputArray mask=noArray() ) const;
返回值:空
queryDescriptors:查询的描述子
trainDescriptors:模板描述子
matches:匹配结果容器
mask:匹配的范围

DMatch的结构
| DMatch的结构

意思
queryIdx
trainIdx
imgIdx
distance

例子:匹配两个图片的特征值
在这里插入图片描述

void Demo::ORBMatch(Mat& src_Template, Mat& src)
{
	//创建ORB
	Ptr<ORB> orb = ORB::create(500, 1.2f, 4);

	//关键点容器
	vector<KeyPoint> template_keyPoints;
	vector<KeyPoint> src_keyPoints;
	//获取关键点
	orb->detect(src_Template, template_keyPoints, Mat());
	orb->detect(src, src_keyPoints, Mat());

	//描述子容器
	Mat template_describe, src_describe;
	//计算描述子
	orb->compute(src_Template, template_keyPoints, template_describe);
	orb->compute(src, src_keyPoints, src_describe);

	//创建匹配模式
	Ptr<BFMatcher> bf_matcher = BFMatcher::create(NORM_HAMMING,false);

	//存储匹配结果
	vector<DMatch> dmatcher;
	//两个描述子进行匹配
	bf_matcher->match(src_describe, template_describe ,dmatcher);

	//过滤距离过大的描述子
	int size = dmatcher.size();
	for (vector<DMatch>::iterator itera = dmatcher.begin(); itera != dmatcher.end();)
	{
		if (itera->distance > 20)
		{
			itera=dmatcher.erase(itera);
		}
		itera++;
	}

	Mat dst;
	//绘制
	drawMatches(src_Template, template_keyPoints, src, src_keyPoints,dmatcher, dst);

	namedWindow("匹配结果", WINDOW_FREERATIO);
	imshow("匹配结果", dst);


}

warpPerspective 透视变换

Mat findHomography( InputArray srcPoints, InputArray dstPoints,
                                 int method = 0, double ransacReprojThreshold = 3,
                                 OutputArray mask=noArray(), const int maxIters = 2000,
                                 const double confidence = 0.995);
返回值:透视变换矩阵
srcPoints:原图像的坐标点
dstpoints:目标坐标点
method:用于计算变换矩阵的方法 0 最小二值法 RANSAC基础鲁棒法 LMEDS - 最小中值鲁棒算法  RHO - PROSAC-基于PROSAC的鲁棒算法
ransacReprojThreshold:将点对视为内点的最大允许重投影错误阈值(仅用于RANSAC和RHO方法)。若srcPoints和dstPoints是以像素为单位的,则该参数通常设置在1到10的范围内。
mask:计算图像区域的掩码
maxlters:RANSAC算法的最大迭代次数,默认值为2000。
confidence:可信度值,取值范围为0到1.
void warpPerspective( InputArray src, OutputArray dst,
                                   InputArray M, Size dsize,
                                   int flags = INTER_LINEAR,
                                   int borderMode = BORDER_CONSTANT,
                                   const Scalar& borderValue = Scalar());
返回值:空
src,原始图像
dst,目标图像
M:变换矩阵
Size:输出图像的大小
flags:插值器
borderMode :边界填充方式
borderValue:边界填充的颜色

例子: 透视变换 校正图片

在这里插入图片描述

void rectifyImage(Mat &src)
{
    Mat  binary,gray;
    Mat dst;
    if(src.channels()>1)
    {
        cvtColor(src, gray, COLOR_BGR2GRAY);
    }
    else
    {
        gray = src.clone();
    }
    //图像二值化
    threshold(gray, binary, 0, 255, THRESH_BINARY_INV | cv::THRESH_OTSU);
    imshow("二值化", binary);
    
    //轮廓检测
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(binary, contours, hierarchy, RETR_LIST, CHAIN_APPROX_NONE, Point());
    int index = 0;
    double maxArea=0;
    
    //发现最大轮廓
    for (int i = 0; i < contours.size(); ++i)
    {
        double area = contourArea(contours[i], false);
        if(area>maxArea)
        {
            index=i;
            maxArea=area;
        }
    }

  
    //轮廓拟合多边形
    vector<Point2f> approxCurve;
    approxPolyDP(contours[index], approxCurve,contours[index].size()*0.1 , true);

    
    //对坐标点进行排序,确保不同图片的坐标点顺序的一致性
    for (int i = 0; i < approxCurve.size(); ++i)
    {
        for (int j = 0; j < approxCurve.size(); ++j)
        {
            if(approxCurve[i].y<approxCurve[j].y)
            {
                Point2f pt=approxCurve[i];
                approxCurve[i]=approxCurve[j];
                approxCurve[j]=pt;
            }
        }
    }
    if(approxCurve[0].x>approxCurve[1].x)
    {
        Point2f pt=approxCurve[0];
        approxCurve[0]=approxCurve[1];
        approxCurve[1]=pt;
    }
    if(approxCurve[2].x>approxCurve[3].x)
    {
        Point2f pt=approxCurve[2];
        approxCurve[2]=approxCurve[3];
        approxCurve[3]=pt;
    }
    

    for (int i = 0; i < approxCurve.size(); ++i)
    {
        cout<<approxCurve[i]<<endl;
    }

    vector<Point2f> dst_keyPoint;

    
    //输入目标点
    dst_keyPoint.push_back(Point2f(0,0));
    dst_keyPoint.push_back(Point2f(300,0));
    dst_keyPoint.push_back(Point2f(0,500));
    dst_keyPoint.push_back(Point2f(300,500));

    cout<<"======================"<<endl;
    for (int i = 0; i < dst_keyPoint.size(); ++i)
    {
        cout<<dst_keyPoint[i]<<endl;
    }

    //获取变换矩阵
    Mat m= findHomography(approxCurve,dst_keyPoint,0);
//透视变换
    warpPerspective(src,dst,m,Size(300,500));

    imshow("结果", dst);

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~搬~运~工~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值