OpenCV笔记
- 1、0到255为CV_8U图像
- 2、计算协方差和均值函数
- 3、Mat图像获取像素点RGB值
- 4、opencv中的像素坐标系定义
- 5、图像掩膜
- 6、返回灰度值不为0的像素数,可用来判断图像是否全黑
- 7、Mat 矩阵初始化及多通道初始化
- 8、矩阵运算
- 9、cvRound(), cvFloor(), cvCeil()函数讲解
- 10、OpenCV中的裁剪与边界值
- 11、Resize改变图像大小
- 12、image.at(y,x)访问cv::Mat数据
- 13、GaussianBlur()高斯滤波
- 14、cv::getTickCount()和cvGetTickCount的区别及用法
- 15、cvConvertScale()
- 16、cv::Ptr<>指针
- 17 、opencv显示Mat float数据
- 18、画二值影像的边缘
- 19、读取Mat为float指针一维数组
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] ;
}
}
}