【opencv】学习笔记记录

这篇博客详细介绍了OpenCV中的图像类型、像素值获取、矩阵运算、图像处理函数等核心概念。包括了从8位无符号整型到32位浮点型的像素表示,如何使用Mat获取RGB值,计算协方差和均值,应用图像掩膜,以及使用countNonZero()判断图像是否全黑。此外,还讨论了矩阵初始化、高斯滤波、图像裁剪与大小调整、以及OpenCV中的时间戳和数据转换函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、0到255为CV_8U图像

0到65535的CV_16U图像
0到1用于CV_32F图像

CV_8U: 1-byte unsigned integer (unsigned char).
CV_32S: 4-byte signed integer (int).
CV_32F: 4-byte floating point (float).

补充:
CV_8UC1,CV_8UC2,CV_8UC3。
(最后的1、2、3表示通道数,譬如RGB3通道就用CV_8UC3)

特别对于深度(depth)和通道(nChannels)的定义,IplImage(图像)和CvMat(矩阵)区别很大,通过上一节,我们知道矩阵的数据类型往往同时表示深度和通道,如8位三元组的无符号整型数据,其结构表示为CV_8UC3。但在图像中,深度和通道数往往是分开处理的。
OpenCV图像类型,可用的深度值如下表:

宏	图像像素类型
IPL_DEPTH_8U	无符号8bit整数(8u)
IPL_DEPTH_8S	有符号8bit整数(8s)
IPL_DEPTH_16S	有符号16bit整数(16s)
IPL_DEPTH_32S	有符号32bit整数(32s)
IPL_DEPTH_32F	32bit浮点数,单精度(32f)
IPL_DEPTH_64F	64bit浮点数,双精度(64f)
通道数nChannels可取的值为:1、2、3或4

2、计算协方差和均值函数

calcCovarMatrix();

3、Mat图像获取像素点RGB值

for(int i=0;i<Image_test.rows;i++)
            for (int j = 0; j < Image_test.cols; j++)
                for (int n = 0; n < Image_test.channels(); n++)
                {
                    int Color=Image_test.at<uchar>(i,j * Image_test.channels() + n) ;
                }

Vec3f intensity  = Mat.at<Vec3f>(y,x)
float blue = intensity.val[0]   //获得蓝色通道的像素值
float green = intensity.val[1]   //获得蓝色通道的像素值
float red = intensity.val[2]      //获得蓝色通道的像素值

int b = srcImage.at<Vec3b>(row, col)[0];  //获取像素值b 
int g = srcImage.at<Vec3b>(row, col)[1];  //获取像素值g
int r = srcImage.at<Vec3b>(row, col)[2];  //获取像素值r

4、opencv中的像素坐标系定义

row == heigh == Point.y
col == width == Point.x
Mat::at(Point(x, y)) == Mat::at(y,x)
在这里插入图片描述

5、图像掩膜

img2.copyTo(img1,mask);
其中img1(结果)、img2(原图)是RGB图像,mask是灰度图像

6、返回灰度值不为0的像素数,可用来判断图像是否全黑

countNonZero();

7、Mat 矩阵初始化及多通道初始化

Mat E = Mat::eye(4,4,CV_64F);
Mat Z = Mat::zeros(4,4,CV_32F);
Mat O = Mat::ones(4,4,CV_8UC1);
分别用来创建一个4*4的单位矩阵,全0矩阵,全1矩阵,类似于Matlab中的矩阵创建。

cv::Mat_<float> A(3,3);
cv::Mat M = cv::Mat::zeros(2, 3, CV_64FC(5));                                             
cv::Mat M2 = cv::Mat::zeros(2, 3, CV_8UC(5));  

8、矩阵运算

cv::Mat.t()表示矩阵的转置

Official Tutorial
https://docs.opencv.org/3.4/d9/df8/tutorial_root.html


#include<iostream>
#include<vector>
#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/features2d/features2d.hpp>
#include<opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;


int main(int argc, char** argv)
{
    //读取图片
    Mat rgbd1 = imread(argv[1],1);
    Mat rgbd2 = imread(argv[2],1);
    //imshow("rgbd1", depth2);
    //waitKey(0);
    Ptr<ORB> orb = ORB::create();
    vector<KeyPoint> Keypoints1,Keypoints2;
    Mat descriptors1,descriptors2;
    orb->detectAndCompute(rgbd1, Mat(), Keypoints1, descriptors1);
    orb->detectAndCompute(rgbd2, Mat(), Keypoints2, descriptors2);
    
    //cout << "Key points of image" << Keypoints.size() << endl;
    
    //可视化,显示关键点
    Mat ShowKeypoints1, ShowKeypoints2;
    drawKeypoints(rgbd1,Keypoints1,ShowKeypoints1);
    drawKeypoints(rgbd2, Keypoints2, ShowKeypoints2);
    imshow("Keypoints1", ShowKeypoints1);
    imshow("Keypoints2", ShowKeypoints2);
    waitKey(0);

    //Matching
    vector<DMatch> matches;
    Ptr<DescriptorMatcher> matcher =DescriptorMatcher::create("BruteForce");
    matcher->match(descriptors1, descriptors2, matches);
    cout << "find out total " << matches.size() << " matches" << endl;

    //可视化
    Mat ShowMatches;
    drawMatches(rgbd1,Keypoints1,rgbd2,Keypoints2,matches,ShowMatches);
    imshow("matches", ShowMatches);
    waitKey(0);


    return 0;
}

9、cvRound(), cvFloor(), cvCeil()函数讲解

  • cvRound():返回跟参数最接近的整数值,即四舍五入;
  • cvFloor():返回不大于参数的最大整数值,即向下取整;
  • cvCeil():返回不小于参数的最小整数值,即向上取整;

10、OpenCV中的裁剪与边界值

使用Rect函数参考博客
copyMakeBorder获取边界值
参考博客1
参考博客2

11、Resize改变图像大小

resize可以将影像缩放到任意尺寸
参考博客

12、image.at(y,x)访问cv::Mat数据

#include<iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
	cv::Mat M2(2, 3,3,CV_8UC1, cv::Scalar::all(0));
	const uchar* center = &(M2.at<uchar>(1, 1));
	M2.at<uchar>(1, 0) = 21;
	M2.at<uchar>(1, 1) = 22;
	M2.at<uchar>(1, 2) = 23;
	cout << int(center[-1]) << endl;;
	std::cout << "M2 = " << std::endl << M2 << std::endl
}

输出结果:M2=21

13、GaussianBlur()高斯滤波

官方文档

14、cv::getTickCount()和cvGetTickCount的区别及用法

参考博客

15、cvConvertScale()

转换数据类型。
CV_8U的转成CV_32F什么的。
还可以同类型拉伸。

16、cv::Ptr<cv::Mat>指针

cv::Ptr<cv::Mat> A(new cv::Mat());
	cv::Mat a(2, 2, CV_32F);
	a.at<float>(0, 0) = 0; a.at<float>(0, 1) = 1; a.at<float>(1, 0) = 10; a.at<float>(1, 1) = 1;
	*A = a;
	float* test = (float*)A->data;
	std::cout << test[0] << "," << test[1] << "," 
	<< test[2] << "," << test[3] << "," << std::endl;

输出:0,1,10,1,

17 、opencv显示Mat float数据

#include<opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
#include<iostream>
using namespace std;
int main()
{
    cv::Ptr<cv::Mat> A(new cv::Mat());
    cv::Mat a(2, 2, CV_32F);
    a.at<float>(0, 0) = 0; a.at<float>(0, 1) = 1; a.at<float>(1, 0) = 100; a.at<float>(1, 1) = 111;
    *A = a;
    float* test = (float*)A->data;
    std::cout << test[0] << "," << test[1] << "," << test[2] << "," << test[3]<< std::endl;
    for (int i = 0; i < sizeof(test); i++)
        test[i] = test[i] / 255;
    imshow("a", *A);
    waitKey(0);
    return 1;
}

输出:0,1,50,111
结果:
在这里插入图片描述

18、画二值影像的边缘

#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
    cv::Mat src_img, img_bool, labels, stats, centroids, img_color, img_gray;

    if ((src_img = cv::imread("C://Users//76760//Desktop//LibTorch//510521luxian_284_label.tif", 0)).empty())
    {
        cout << "error";
        return -1;
    }
    cv::threshold(src_img, img_bool, 0, 255, cv::THRESH_OTSU);
    //连通域计算
    int nccomps = cv::connectedComponentsWithStats(
        img_bool, //二值图像
        labels,     //和原图一样大的标记图
        stats, //nccomps×5的矩阵 表示每个连通区域的外接矩形和面积(pixel)
        centroids //nccomps×2的矩阵 表示每个连通区域的质心
    );
    //显示原图统计结果
    char title[1024];
    std::cout << "yuanshi:" << nccomps << std::endl;
    cv::String num_connect(title);
    cv::imshow(num_connect, img_bool);

    //去除过小区域,初始化颜色表
    vector<cv::Vec3b> colors(nccomps);
    colors[0] = cv::Vec3b(0, 0, 0); // background pixels remain black.
    for (int i = 1; i < nccomps; i++) {
        colors[i] = cv::Vec3b(rand() % 256, rand() % 256, rand() % 256);
        //去除面积小于100的连通域
        if (stats.at<int>(i, cv::CC_STAT_AREA) < 100)
            colors[i] = cv::Vec3b(0, 0, 0); // small regions are painted with black too.
    }
    //按照label值,对不同的连通域进行着色
    img_color = cv::Mat::zeros(src_img.size(), CV_8UC3);
    for (int y = 0; y < img_color.rows; y++)
        for (int x = 0; x < img_color.cols; x++)
        {
            int label = labels.at<int>(y, x);
            CV_Assert(0 <= label && label <= nccomps);
            img_color.at<cv::Vec3b>(y, x) = colors[label];
        }

    //统计降噪后的连通区域
    cv::cvtColor(img_color, img_gray, cv::COLOR_BGR2GRAY);
    cv::threshold(img_gray, img_gray, 1, 255, cv::THRESH_BINARY);
    nccomps = cv::connectedComponentsWithStats(img_gray, labels, stats, centroids);
    std::cout << "guolv:" << nccomps << std::endl;
    num_connect = title;
    cv::imshow(num_connect, img_color);
    cv::waitKey();
    return 0;
}

19、读取Mat为float指针一维数组

static float data[INPUT_C * INPUT_H * INPUT_W];//CHW
for (int c = 0; c < 4; ++c)
	{

		for (int i = 0; i < image_nir.rows; ++i)
		{ //获取第i行首像素指针 
			cv::Vec4f* p1 = image_nir.ptr<cv::Vec4f>(i);
			//cv::Vec3b *p2 = image.ptr<cv::Vec3b>(i);
			for (int j = 0; j < image_nir.cols; ++j)
			{
				data[c * 512 * 512 + i * 512 + j] = p1[j][c] ;

			}
		}

	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值