关于Mat类,我们首先要知道的是:
(1)不必再手动为其开辟空间。
(2)不必再在不需要时立即将空间释放
总结:
Mat B(A)
只复制信息头clone()
或者 copyTo()
来复制一副图像的矩阵【方法一】使用Mat()构造函数
Mat M(2,2,CV_8UC3,Scalar(0,0,255));
//CV_[位数][带符号与否][类型前缀]C[通道数]
//预先定义的通道数可以多达4个
【方法二】在C/C++中通过构造函数进行初始化
int sz[3]={2,2,2};
Mat L(3,sz,cv_8UC,Scalar::all(0));
//上面的例子演示了如何创建一个超过两维的矩阵:指定维数,然后传递给一个指向数组的指针,这个数组包含每个维度的尺寸;后续两个参数与方法一中的相同
【方法三】为已存在的IplImage指针创建信息头
IplImage* img = cvLoadImage("1.jpg",1);
Mat mtx(img);//转换 IplImage*->Mat
【方法四】利用Create()函数
M.create(4,4,CV_8UC(2));
//需要注意的是,此方法不能为矩阵设初值,只是在该百年尺寸时重新为矩阵数据开辟内存而已。
【方法六】对小矩阵使用逗号分隔式初始化函数
Mat C = (Mat_<double>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
cout<<"C = "<<endl<<" "<C<<endl<<endl;
【方法七】为已存在的对象创建新信息头
Mat RowClone = C.row(1).clone();
cout<<"RowClone = "<<endl<<" "<<RowClone<<endl<<endl;
//方法七为使用成员函数clone()或者copyTo()为一个已存在的Mat对象创建一个新的信息头
获取图像像素指针
掩码操作解释
代码演示
像素处理范围 saturate_cast<uchar>
这个函数的功能是确保RGB值得范围在0~255之间
掩码操作实现图像对比度的调整 I ( i , j ) = 5 ∗ I ( i , j ) − [ I ( i − 1 , j ) + I ( i + 1 , j ) + I ( i , j − 1 ) , I ( i , j + 1 ) ] I(i,j)=5*I(i,j)-[I(i-1,j)+I(i+1,j)+I(i,j-1),I(i,j+1)] I(i,j)=5∗I(i,j)−[I(i−1,j)+I(i+1,j)+I(i,j−1),I(i,j+1)]
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
int main(int argc,char** argv)
{
Mat src = imread("test.jpg");
Mat dst;
if (!src.data)//如果图像为空,返回 error
{
std::cout << "can't load this img" <<std::endl;
return -1;
}
namedWindow("input image", WINDOW_AUTOSIZE);
imshow("input image", src);
//RGB图像按列存储,注意存储顺序是BGR
int cols = (src.cols - 1) * src.channels();
//cols 应该用width更为妥当,-1是因为要空出一列像素以防无定义
int offsetx = src.channels();
//偏移量是通道数
int rows = src.rows;
//RGB按照列存储,与行数无关
dst = Mat::zeros(src.size(), src.type());
//重新创建一个mat矩阵用于存放输出的图像
//src.copyTo(dst);也可
for (int row = 1; row < rows - 1; row++) {
const uchar* previous = src.ptr<uchar>(row - 1);
const uchar* current = src.ptr<uchar>(row);
const uchar* next = src.ptr<uchar>(row +1);
//创建核的数组
uchar* output = dst.ptr<uchar>(row);
for (int col = offsetx; col < cols; col++) {
output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col]));
}
}
namedWindow("constrast image", WINDOW_AUTOSIZE);
imshow("constrast image", dst);
waitKey(0);
return 0;
}
可直接用opencv的API做掩码操作来提高对比度
filter2D(src,dst,src.depth(),kernel):其中src与dst是Mat类型变量,src.depth表示位图深度,有32、24、8等,直接写-1表示与输入图深度一致。(filter滤波器)
定义掩码: Mat lernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
#include <opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
#include<stdlib.h>
using namespace cv;
int main(int argc, char** argv) {
Mat src = imread("C:/Users/admin/Desktop/lenna.png");//读入图片
Mat dst;//提高对比度之后的图片矩阵
if (src.empty()){ // 特判
printf("cannot see\n");
return -1;
}
namedWindow("opencv setup1", CV_WINDOW_AUTOSIZE);
imshow("opencv setup1", src);
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//定义掩码规则
filter2D(src, dst, src.depth()/*-1*/, kernel);
//输出目标图像
namedWindow("opencv setup2", CV_WINDOW_AUTOSIZE);
imshow("opencv setup2", dst);
waitKey(0);
system("pause"); //以便在退出程序前调用系统的暂停命令暂停命令行
//爽得很!!
}
mat对象的使用:
Mat F=A.clone();
//或者
Mat G;
A.copyTo(G);
函数用法:
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc,char** argv)
{
Mat src = imread("test.jpg");
if (!src.data)
{
std::cout << "can't load this img" <<std::endl;
return -1;
}
//namedWindow("input image", WINDOW_AUTOSIZE);
//imshow("input image", src);
/*Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(255, 0, 255);
namedWindow("out put", WINDOW_AUTOSIZE);
imshow("out put", dst);*/
/*Mat dst = src.clone();
namedWindow("out put", WINDOW_AUTOSIZE);
imshow("out put", dst);*/
//Mat dst;
//cvtColor(src, dst, COLOR_BGR2GRAY);
//namedWindow("out put", WINDOW_AUTOSIZE);
//imshow("out put", dst);
//cout << src.channels() << endl;//通道数目
//cout << dst.channels() << endl;
//int cols = dst.cols;//全部的列
//int rows = dst.rows;//全部的行
//const uchar* firstRow = dst.ptr<uchar>(0);
//printf("%d", *firstRow);
Mat M(3, 3, CV_8UC3, Scalar(0, 0, 255));
Mat m1;
m1.create(src.size(),src.type());
m1=Scalar(0,0,255);
Mat m2 = Mat::zeros(src.size(),src.type());
Mat m2 = Mat::zeros(2,2,CV_8UC1);
Mat m2 = Mat::eye(2,2,CV_8UC1);
cout << M << endl;
waitKey(0);
return 0;
}
imread
可以指定加载为灰度图像或者RGB图像imwrite
保存图像文件,类型由扩展名决定Scalar intensity = img.at<uchar>(y,x);
或者
Scalar intensity = img.at<uchar>(Point(y,x));
Vec3f intensity = img.at<Vec3f>(y,x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];
获取像素的练习
#include <opencv2/core/utils/logger.hpp>
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
cv::utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//不再输出日志
Mat src = imread("test.jpg");
if (!src.data) {
cout << "could not load this image..." << endl;
}
char output_origin[] = "origin demo";
char output_gray[] = "gray demo";
namedWindow(output_origin, WINDOW_AUTOSIZE);
imshow(output_origin, src);
Mat dst;
cvtColor(src, dst, COLOR_BGR2GRAY);
namedWindow(output_gray, WINDOW_AUTOSIZE);
imshow(output_gray, dst);
dst.create(src.size(), src.type());
for (int row = 0; row < dst.rows; row++)
for (int col = 0; col <dst.cols; col++) {
//int gray = dst.at<uchar>(row,col);
//dst.at<uchar>(row,col) = 255 - gray;
int b = src.at<Vec3b>(row, col)[0];
int g = src.at<Vec3b>(row, col)[1];
int r = src.at<Vec3b>(row, col)[2];
dst.at<Vec3b>(row, col)[0]=255-b;
dst.at<Vec3b>(row, col)[1] = 255 -g;
dst.at<Vec3b>(row, col)[2] = 255 - r;
//另一种转换成灰度图像的方法:
//dst.at<uchar>(row,col)=max(r,max(b,g));
//dst.at<uchar>(row,col)=min(r,min(b,g));
}
namedWindow("anti color demo", WINDOW_AUTOSIZE);
imshow("anti color demo", dst);
waitKey(0);
}
//已经有封装好的API干嘛要练习这个
bitwise_not(src,dst);
Vec3b对应的三通道的顺序是blue、green、red的uchar类型的数据
Vec3f对应三通道的float类型数据
把CV_8UC1转换到CV32F1实现如下: src.convertTo(dst,CV_32F);
g ( x ) = ( 1 − α ) f 0 ( x ) + α f 1 ( x ) 其中 α 的取值范围为 0 到 1 之间 g(x)=(1-\alpha)f_0(x)+\alpha f_1(x)\\其中\alpha的取值范围为0到1之间 g(x)=(1−α)f0(x)+αf1(x)其中α的取值范围为0到1之间
相关的API(addWeighted):
addWeight(src1,alpha,src2,beta,gamma(校验值),dst);
d s t ( I ) = s a t u r a t e _ c a s t ( s r c 1 ( I ) ∗ a l p h a + s r c 2 ( I ) ∗ b e t a + g a m m a ) dst(I)=saturate\_cast(src1(I)*alpha+src2(I)*beta+gamma) dst(I)=saturate_cast(src1(I)∗alpha+src2(I)∗beta+gamma)
理论:
图像变换可以看作如下:
调整图像亮度属于像素变换-点操作 g ( i , j ) = α f ( i , j ) + β g(i,j)=\alpha f(i,j)+\beta g(i,j)=αf(i,j)+β其中 α \alpha α>0, β \beta β是增益变量
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src = imread("test.jpg");
char input_win[] = "src image";
if (!src.data) {
cout << "could not load the image..." << endl;
}
namedWindow(input_win, WINDOW_AUTOSIZE);
imshow(input_win, src);
Mat dst;
int height = src.rows;
int width = src.cols;
dst = Mat::zeros(src.size(), src.type());
double alpha = 1.5;
double beta = 10;
src.convertTo(src, CV_32F);
for (int row = 0; row < height; row++)
for (int col = 0; col < width; col++) {
if (src.channels() 3) {
float b = src.at<Vec3f>(row, col)[0];
float g = src.at<Vec3f>(row, col)[1];
float r = src.at<Vec3f>(row, col)[2];
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b * alpha + beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g * alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r * alpha + beta);
}
else if (src.channels() 1) {
int v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v * alpha + beta);
}
//else
}
char output_title[] = "contrast and brightness change demo";
namedWindow(output_title, WINDOW_AUTOSIZE);
imshow(output_title, dst);
waitKey(0);
}
使用Point与Scalar
Point表示2D平面上一个点(x,y)
Point p;
p.x=10;p.y=8;//p=Point(10,8);
Scalar表示四个元素的向量
Scalar(a,b,c);//a=bule,b=green,c=red表示RGB三个通道
在图片中插入线、矩形、椭圆、圆、多边形。
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
Mat src;
void lines();
void myRectangle();
void myEllipse();
void myCircle();
void myPolygon();
int main(int argc, char** argv)
{
src = imread("test.jpg");
if (!src.data) {
cout << "could not liad this image.." << endl;
return -1;
}
lines();
myRectangle();
myEllipse();
myCircle();
myPolygon();
namedWindow("line_demo", WINDOW_AUTOSIZE);
imshow("line_demo", src);
waitKey(0);
}
void lines() {//线
Point p1 = Point(20, 30);
Point p2 = Point(200, 300);
Scalar color =Scalar(0, 0, 255);
line(src, p1, p2, color, 5, LINE_AA);
}
void myRectangle() {//矩形
Rect rect = Rect(200, 100, 300, 300);
Scalar color = Scalar(0, 0, 255);
rectangle(src, rect, color,1, LINE_8);
}
void myEllipse() {//椭圆
Scalar color = Scalar(175, 145, 76);
ellipse(src, Point(src.cols/ 2, src.rows / 2), Size(src.rows / 4, src.cols / 8), 0, 0, 360, color, 1, LINE_AA);
}
void myCircle() {//圆
Scalar color = Scalar(175, 146, 76);
circle(src, Point(src.cols / 2, src.rows / 2), src.cols / 4, color, 1, LINE_AA);
}
void myPolygon() {//多边形
Scalar color = Scalar(0, 0, 255);
Point pts [1][6];
pts[0][0] = Point(100, 100);
pts[0][1] = Point(100, 200);
pts[0][2] = Point(200, 200);
pts[0][3] = Point(200, 100);
pts[0][4] = Point(150, 50);
pts[0][5] = Point(100, 100);
const Point* ppts[] = { pts[0] };
int npt[] = { 6 };
fillPoly(src, ppts, npt, 1, color, 8);
}
在图像中插入文字。putText();
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
Mat src;
int main(int argc, char** argv)
{
src = imread("test.jpg");
if (!src.data) {
cout << "could not liad this image.." << endl;
return -1;
}
putText(src, "hello opencv", Point(src.cols / 2-60, src.rows / 2), FONT_HERSHEY_COMPLEX, 0.8, Scalar(150, 12, 255), 1, 8);
namedWindow("line_demo", WINDOW_AUTOSIZE);
imshow("line_demo", src);
waitKey(0);
}
//随机生成颜色
随机生成线条
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
Mat src;
void RandowLineDemo();
int main(int argc, char** argv)
{
src = imread("test.jpg");
if (!src.data) {
cout << "could not liad this image.." << endl;
return -1;
}
//putText(src, "hello opencv", Point(src.cols / 2-60, src.rows / 2), FONT_HERSHEY_COMPLEX, 0.8, Scalar(150, 12, 255), 1, 8);
RandowLineDemo();
//namedWindow("line_demo", WINDOW_AUTOSIZE);
//imshow("line_demo", src);
waitKey(0);
}
void RandowLineDemo() {
RNG rng(12346);//RNG 变量(种子数)
Mat bg = Mat::zeros(src.size(), src.type());
for (int i = 0; i < 10000; i++) {
line(bg, Point(rng.uniform(0, src.cols), rng.uniform(0, src.rows)), Point(rng.uniform(0, src.cols), rng.uniform(0, src.rows)), Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 1, LINE_AA);
//rng.uniform(范围);
if (waitKey(50) > 0) {
break;
}
imshow("RandowLineDemo", bg);
}
}
blur(Mat src,Mat dst,Size(xradius,yradius),Point(-1,-1));
GaussianBlur(Mat src,Mat dst,Size(11,11),sigmax,sigmay);
其中Size(x,y)必须是正数而且是奇数。均值模糊
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
Mat src, dst;
src = imread("test.jpg");
if (src.empty()) {
cout << "could not load this image..." << endl;
return -1;
}
namedWindow("originalDemo", WINDOW_AUTOSIZE);
imshow("originalDemo", src);
blur(src, dst, Size(3, 3), Point(-1, -1));
namedWindow("blur3Demo", WINDOW_AUTOSIZE);
imshow("blur3Demo", dst);
blur(src, dst, Size(5, 5), Point(-1, -1));
namedWindow("blur5Demo", WINDOW_AUTOSIZE);
imshow("blur5Demo", dst);
waitKey(0);
}
高斯模糊
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
Mat src, dst;
src = imread("test.jpg");
if (src.empty()) {
cout << "could not load this image..." << endl;
return -1;
}
namedWindow("originalDemo", WINDOW_AUTOSIZE);
imshow("originalDemo", src);
GaussianBlur(src, dst, Size(11, 11), 5, 5);
namedWindow("GaussianBlurDemo", WINDOW_AUTOSIZE);
imshow("GaussianBlurDemo", dst);
//blur(src, dst, Size(5, 5), Point(-1, -1));
//namedWindow("blur5Demo", WINDOW_AUTOSIZE);
//imshow("blur5Demo", dst);
waitKey(0);
}
medianBlur(Mat src,Mat dest,ksize)
bilateralFilter(src,dest,d=15,150,3);
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main() {
Mat src, dst;
src = imread("cat1.jpg");
if (src.empty()) {
cout << "could not load this image..." << endl;
return -1;
}
namedWindow("originalDemo", WINDOW_AUTOSIZE);
imshow("originalDemo", src);
//GaussianBlur(src, dst, Size(11, 11), 5, 5);
//medianBlur(src, dst, 3);
bilateralFilter(src, dst, 15, 150, 3);
namedWindow("BilateralFilterDemo", WINDOW_AUTOSIZE);
imshow("BilateralFilterDemo", dst);
waitKey(0);
}
getStructuringElement(int shape,Size ksize,Point anchor)
dilate(src,dst,kernel)
erode(src,dst,kernel)
createTrackbar(constString&trackbarname,winname,int*value,int count,Trackbarcallback func,void* userdata=0)
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
void CallBack_Demo(int, void*);//回调函数
int element_size = 3;
int Max_size = 21;
Mat src, dst;
int main()
{
src = imread("cat1.jpg");
if (!src.data)
{
cout << "could not load this image.." << endl;
return -1;
}
namedWindow("input image", WINDOW_AUTOSIZE);
imshow("input image", src);
namedWindow("output image", WINDOW_AUTOSIZE);
createTrackbar("Element Size:", "output image", &element_size, Max_size, CallBack_Demo);
CallBack_Demo(0, 0);
waitKey(0);
return 0;
}
void CallBack_Demo(int, void*)
{
int s = element_size * 2 + 1;
Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
//dilate(src, dst, structureElement, Point(-1, -1), 1);//膨胀
erode(src, dst, structureElement, Point(-1, -1), 1);//腐蚀
imshow("output image", dst);
return;
}
//深入理解createTrackBar函数
#include<opencv2/opencv.hpp>
#include<iostream>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//void CallBack_Demo(int, void*);
int element_size = 3;
int Max_size = 21;
Mat src, dst;
void text(int, void*) {
cout << element_size << endl;
}
int main()
{
src = imread("cat1.jpg");
if (!src.data)
{
cout << "could not load this image.." << endl;
return -1;
}
namedWindow("测试窗口", WINDOW_AUTOSIZE);
createTrackbar("数字", "测试窗口", &element_size, Max_size, text);
text(0, 0);
waitKey(0);
return 0;
}
morphologyEx(src,dest,CV_MOP_BLACKHAT,kernel);
针对二值图像进行处理
膨胀:输出的像素值是结构元素覆盖下输入图像的最大像素值
腐蚀:输出的像素值是结构元素覆盖下输入图像的最小像素值
结构元素
提取步骤
bitwise_not(src,dst):dst=255-src;
代码样例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src,temp, dst;
src = imread("0-1.jpg");
if (src.empty()) {
cout << "could not load this img..." << endl;
return -1;
}
imshow("src", src);
cvtColor(src, temp, COLOR_BGR2GRAY);
adaptiveThreshold(temp, temp, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
Mat x_kernel = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));
Mat y_kernel = getStructuringElement(MORPH_RECT, Size(1,src.rows/16), Point(-1, -1));
morphologyEx(temp, dst, MORPH_OPEN, x_kernel);
bitwise_not(dst, dst);
blur(dst,dst,Size(3,3),Point(-1,-1));
namedWindow("x_line", WINDOW_AUTOSIZE);
imshow("x_line", dst);
waitKey(0);
return 0;
}
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src,temp, dst;
src = imread("ganrao.png");
if (src.empty()) {
cout << "could not load this img..." << endl;
return -1;
}
imshow("src", src);
cvtColor(src, temp, COLOR_BGR2GRAY);
adaptiveThreshold(temp, temp, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);//自适应阈值,可以转换为二值图像
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//核,getstructingelement获取结构元素
morphologyEx(temp, dst, MORPH_OPEN, kernel);
//形态学操作--开--morph——open
bitwise_not(dst, dst);
imshow("干扰去除", dst);
waitKey(0);
return 0;
}
图像金字塔概念
采样API
如何进行上采样和降采样从而得到高斯金字塔的图像,在一个是如何对每一层进行处理得到它的DOG,归一化,彩色图像通道也可做DOG
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src,temp, g1,g2,dogImg;
src = imread("test.jpg");
if (src.empty()) {
cout << "could not load this img..." << endl;
return -1;
}
imshow("src", src);
//DOG
cvtColor(src, temp, COLOR_BGR2GRAY);//转换为灰度图像
GaussianBlur(temp, g1, Size(3, 3), 0, 0);//两次高斯模糊
GaussianBlur(g1, g2, Size(3, 3), 0,0);
subtract(g1, g2, dogImg, Mat());//减去
//归一化显示
normalize(dogImg, dogImg, 255, 0, NORM_MINMAX);//用此函数也可化为0-1图像
imshow("DOG Image", dogImg);
waitKey(0);
return 0;
}
阈值二值化(threshold binary)
阈值反二值化(threshold binary Inverted)
阈值截断(threshold trunc)
阈值取零(threshold to zero)
阈值反取零(threshold to zero Inverted)
首先转化为灰度图像
阈值操作
threshold(src,dst,threshold_value,threshold_max,THRESH_TYPE);
#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
using namespace cv;
using namespace std;
int threshold_value = 127;//阈值
int threshold_max = 255;//最大阈值
Mat src, dst;
void threshold_Demo(int, void*);//声明回调函数
int main(int argc, char** argv) {
src = imread("test.jpg");
if (src.empty()) {
cout << "could not load this img..." << endl;
return -1;
}
namedWindow("input image", WINDOW_AUTOSIZE);
namedWindow("output image", WINDOW_AUTOSIZE);
imshow("input image", src);
createTrackbar("threshold", "output image", &threshold_value, threshold_max, threshold_Demo);//创建滑动条
threshold_Demo(0, 0);
waitKey(0);
return 0;
}
void threshold_Demo(int, void*) {
cvtColor(src, dst, COLOR_BGR2GRAY);//转换为灰度图
threshold(dst, dst, threshold_value, threshold_max, THRESH_BINARY);//转换为二值图像
imshow("output image", dst);
}
XML是使用非常广泛的文件格式,可以利用XML或者YAML格式的文件存储和还原各式各样的数据结构。当然,他们还可以存储和载入任意复杂的数据结构,其中就包括了OpenCV相关周边的数据结构,以及各种原始数据类型,如整数和浮点数字和文本字符串。
过程:
FileStorage
类的对象,用默认带参数的构造函数完成初始化,或者用 FileStorage::open()
成员函数辅助初始化。FileStorage::release()
函数析构掉 FileStorage
类对象,同时关闭文件。#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
#include<time.h>
using namespace cv;
using namespace std;
int main() {
//初始化
FileStorage fs("test.yaml", FileStorage::WRITE);
fs << "frameCount" << 5;
time_t rawtime;
time(&rawtime);
fs << "calibrationDate" << asctime(localtime(&rawtime));
Mat cameraMatrix = (Mat_<double>(3, 3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
Mat distCoeffs = (Mat_<double>(5, 1) << 0.1, 0.01, -0.001, 0, 0);
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
fs << "features" << "[";
for (int i = 0; i < 3; i++)
{
int x = rand() % 640;
int y = rand() % 480;
uchar lbp = rand() % 256;
fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
for (int j = 0; j < 8; j++)
fs << ((lbp >> j) & 1);
fs << "]" << "}";
}
fs << "]";
fs.release();
return 0;
}
模板也是一个小的图像,用小图像匹配的过程叫做模板匹配
从左到右,从上到下计算匹配度
计算归一化平方不同TM_SQDIFF_NORMED -1
计算归一化相关性TM_CCORR_NORMED ----3
计算归一化相关系数TM_CCOEFF_NORMED -----5
相关API介绍
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
using namespace std;
int trackbar_value = TM_CCOEFF_NORMED;//阈值,
int max_track = 5;//最大阈值/类型数目
Mat src, temp, dst;
void templateMatch_demo(int, void*);
int main(int argc, char** argv) {
src = imread("src.jpg");
temp = imread("template.jpg");
if (!src.data || !temp.data) {
cout << "could not load this image..." << endl;
return -1;
}
//namedWindow("input img", WINDOW_AUTOSIZE);
namedWindow("output img", WINDOW_AUTOSIZE);
createTrackbar("templatemacth", "output img", &trackbar_value, max_track, templateMatch_demo);//创建滑动条
templateMatch_demo(0, 0);
waitKey(0);
}
void templateMatch_demo(int ,void*) {
int height = src.rows - temp.rows + 1;//格式要求:大-小+1
int width = src.cols - temp.cols + 1;
Mat result(width, height, CV_32FC1);//要求输出32位单通道用于模板匹配
matchTemplate(src, temp, result, trackbar_value,Mat());//模板匹配
normalize(result, result, 0, 1, NORM_MINMAX,-1,Mat());//归一化0-1图像
Point minLoc, maxLoc,temLoc;//定位
src.copyTo(dst);//把源图像给dst
double min, max;
minMaxLoc(result, &min, &max, &minLoc, &maxLoc,Mat());
if (trackbar_value TM_SQDIFF || trackbar_value TM_SQDIFF_NORMED) {
temLoc = minLoc;
}
else temLoc = maxLoc;
rectangle(dst, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255),2,8);//在dst上画出框
rectangle(result, Rect(temLoc.x, temLoc.y, temp.cols, temp.rows), Scalar(0, 0, 255),2,8);
imshow("output img", result);
imshow("match", dst);
}
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int threshold_value = 100;
int threshold_max = 255;
Mat src, dst;
void Demo_Contours(int, void*);
RNG rng;
int main() {
src = imread("cat3.jpg");
if (src.empty()) {
cout << "could not load this image..." << endl;
return -1;
}
Demo_Contours(0, 0);//contours轮廓
waitKey(0);
return 0;
}
void Demo_Contours(int, void*) {
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
Canny(src, dst, threshold_value, threshold_value * 2, 3, false);
//Canny(输入,输出,低阈值,高阈值(低阈值的2·3倍),3,false);
findContours(dst, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//寻找轮廓
Mat drawImg = Mat::zeros(dst.size(), CV_8UC3);//8bit3通道的彩色图像
for (size_t i = 0; i < contours.size(); i++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//RNG rng生成一个随机数。
drawContours(drawImg, contours, i, color, 2, LINE_8, hierarchy, 0, Point(0, 0));//画出轮廓(颜色随机),
}
imshow("output", drawImg);
}
Graham扫描算法
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int threshold_value = 100;
int threshold_max = 255;
Mat src,src_gray;
void Thershold_Callback(int, void*);
RNG rng(12345);
const char* OUTPUT = "output";
const char* TRACKBAR = "trackbar";
int main() {
src = imread("cat1.jpg");
if (src.empty()) {
cout << "could not load this image..." << endl;
return -1;
}
cvtColor(src, src_gray, COLOR_BGR2GRAY);//先转化为灰度图像
blur(src_gray, src_gray, Size(3, 3), Point(-1, -1));//然后进行模糊,降低噪声,以用来更好的二值化
namedWindow(OUTPUT, WINDOW_AUTOSIZE);
createTrackbar(TRACKBAR, OUTPUT, &threshold_value, threshold_max, Thershold_Callback);
Thershold_Callback(0, 0);
waitKey(0);
return 0;
}
void Thershold_Callback(int, void*) {
Mat threshold_output;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
threshold(src_gray, threshold_output, threshold_value, threshold_max, THRESH_BINARY);//转化为二值图像
findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));//通过发现轮廓的到候选点
vector<vector<Point>> hull(contours.size());
for (size_t i = 0; i < contours.size(); i++) {
convexHull(Mat(contours[i]), hull[i], false);
}
Mat dst = Mat::zeros(threshold_output.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(dst, hull, i, color, 1, LINE_8, hierarchy, 0, Point(0, 0));
drawContours(dst, contours, i, color, 1, LINE_8, hierarchy, 0, Point(0, 0));
}
imshow(OUTPUT, dst);
}
从彩色图像转化为灰度图像,然后进行模糊,然后进行二值化处理,或者使用Canny边缘检测
approxPolyDP(InputArray curve,OutputArray approxCurve,double epsilon,bool closed)
基于RDP算法实现,目的是减少多边形轮廓点数boundingRect(InputArray points)
得到轮廓周围最小矩形左上角点坐标和右下角点坐标,绘制一个矩形minAreaRect(InputArray points)
得到一个旋转的矩形,返回旋转矩形minEnclosingCircle(InputArray points)
//得到最小区域圆形
fitEllipse(InputArray points)
得到最小椭圆findContours
)//坏代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int threshold_value = 170;
int threshold_max = 255;
Mat src, src_gray, dst;
void Contours_Callback(int, void*);
RNG rng(12345);
const char* OUTPUT = "rectangle-Demo";
const char* TRACKBAR = "trackbar";
int main() {
src = imread("cat1.jpg");
if (src.empty()) {
cout << "could not load this image..." << endl;
return -1;
}
cvtColor(src, src_gray, COLOR_BGR2GRAY);//先转化为灰度图像
blur(src_gray, src_gray, Size(3, 3), Point(-1, -1));//然后进行模糊,降低噪声,以用来更好的二值化
namedWindow(OUTPUT, WINDOW_AUTOSIZE);
createTrackbar(TRACKBAR, OUTPUT, &threshold_value, threshold_max, Contours_Callback);
Contours_Callback(0, 0);
waitKey(0);
return 0;
}
void Contours_Callback(int, void*) {
Mat binary_output;//把灰度图像变为二值图像
vector<vector<Point>>contours;
vector<Vec4i> hierachy;
threshold(src_gray, binary_output, threshold_value, threshold_max, THRESH_BINARY);
findContours(binary_output, contours, hierachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));
vector<vector<Point>>contours_ploy(contours.size());
vector<Rect>ploy_rects(contours.size());
vector<Point2f> ccs(contours.size());
vector<float> radius(contours.size());
vector<RotatedRect> minRect(contours.size());
vector<RotatedRect> myellipse(contours.size());
for (size_t i = 0; i < contours.size(); i++) {
approxPolyDP(Mat(contours[i]), contours_ploy[i], 3, true);//初始化
/*ploy_rects[i] = boundingRect(contours_ploy[i]);
minEnclosingCircle(contours_ploy[i], ccs[i], radius[i]);*/
if (contours_ploy.size() > 5) {
myellipse[i] = fitEllipse(contours_ploy[i]);
minRect[i] = minAreaRect(contours_ploy[i]);
}
}
src.copyTo(dst);
Point2f pts[4];
for (size_t i = 0; i < contours.size(); i++) {
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
if (contours_ploy.size() > 5) {
//rectangle(dst, ploy_rects[i], color, 2, LINE_8);
//circle(dst, ccs[i], radius[i], color, 2, LINE_8);
ellipse(dst, myellipse[i], color, 1, LINE_8);
minRect[i].points(pts);
for (int r = 0; r < 4; r++) {
line(dst, pts[r], pts[(r + 1) % 4], color, 1, LINE_8);
}
}
}
imshow(OUTPUT, dst);
}
持续更新…
自用整理,仅为了记录,如需转载请标明出处。
文章浏览阅读1.3k次,点赞40次,收藏19次。虽然你不能直接计算每个房间的人数,但通过马尔科夫链的蒙特卡洛方法,你可以从任意状态(房间)开始采样,并最终收敛到目标分布(人数分布)。然后,根据一个规则(假设转移概率是基于房间的人数,人数较多的房间具有较高的转移概率),你随机选择一个相邻的房间作为下一个状态。比如在巨大城堡,里面有很多房间,找到每个房间里的人数分布情况(每个房间被访问的次数),但是你不能一次进入所有的房间并计数。但是,当你重复这个过程很多次时,你会发现你更有可能停留在人数更多的房间,而在人数较少的房间停留的次数较少。_马尔科夫链期望怎么求
文章浏览阅读3.9k次。一、su命令su命令用于切换当前用户身份到其他用户身份,变更时须输入所要变更的用户帐号与密码。命令su的格式为:su [-] username1、后面可以跟 ‘-‘ 也可以不跟,普通用户su不加username时就是切换到root用户,当然root用户同样可以su到普通用户。 ‘-‘ 这个字符的作用是,加上后会初始化当前用户的各种环境变量。下面看下加‘-’和不加‘-’的区别:root用户切换到普通..._限制su root登陆
文章浏览阅读1.2k次。精通VC与Matlab联合编程(六)作者:邓科下载源代码浅析VC与MATLAB联合编程浅析VC与MATLAB联合编程浅析VC与MATLAB联合编程浅析VC与MATLAB联合编程浅析VC与MATLAB联合编程 Matlab C/C++函数库是Matlab扩展功能重要的组成部分,包含了大量的用C/C++语言重新编写的Matlab函数,主要包括初等数学函数、线形代数函数、矩阵操作函数、数值计算函数_精通vc和matlab联合编程 六
文章浏览阅读128次。在MVC2中默认并没有实现DescriptionAttribute(虽然可以找到这个属性,通过阅读MVC源码,发现并没有实现方法),这很不方便,特别是我们使用EditorForModel的时候,我们需要对字段进行简要的介绍,下面来扩展这个属性。新建类 DescriptionMetadataProvider然后重写DataAnnotationsModelMetadataPro..._asp.net mvc 模型description
文章浏览阅读1.3k次。一.概述 本篇继续探讨web应用架构,讲基于DDD风格下最初的领域模型架构,不同于DDD风格下CQRS架构,二者架构主要区别是领域层的变化。 架构的演变是从领域模型到C..._eshoponweb
文章浏览阅读2.6w次,点赞23次,收藏85次。首先说明,本人之前没用过zookeeper、kafka等,尚硅谷十几个小时的教程实在没有耐心看,现在我也不知道分区、副本之类的概念。用kafka只是听说他比RabbitMQ快,我也是昨天晚上刚使用,下文中若有讲错的地方或者我的理解与它的本质有偏差的地方请包涵。此文背景的环境是windows,linux流程也差不多。 官网下载kafka,选择Binary downloads Apache Kafka 解压在D盘下或者什么地方,注意不要放在桌面等绝对路径太长的地方 打开conf_springboot kafka
文章浏览阅读1k次。编好水晶报表代码,用的是ActiveX模式,在本机运行,第一次运行提示安装ActiveX控件,安装后,一切正常,能正常打印,但发布到网站那边运行,可能是一闪而过,连提示安装ActiveX控件也没有,甚至相关的功能图标都不能正常显示,再点"打印图标"也是没反应解决方法是: 1.先下载"PrintControl.cab" http://support.businessobjects.c_水晶报表 不能打印
文章浏览阅读1.3k次。绝大部分UC/OS-II的源码是用移植性很强的ANSI C写的。也就是说某产品可以只使用很少几个UC/OS-II调用,而另一个产品则使用了几乎所有UC/OS-II的功能,这样可以减少产品中的UC/OS-II所需的存储器空间(RAM和ROM)。UC/OS-II是为嵌入式应用而设计的,这就意味着,只要用户有固化手段(C编译、连接、下载和固化), UC/OS-II可以嵌入到用户的产品中成为产品的一部分。1998年uC/OS-II,目前的版本uC/OS -II V2.61,2.72。1.UC/OS-Ⅱ简介。_ucos
文章浏览阅读614次,点赞22次,收藏11次。大家好,本文将围绕python自动化运维需要掌握的技能展开说明,python自动化运维从入门到精通是一个很多人都想弄明白的事情,想搞清楚python自动化运维快速入门 pdf需要先了解以下几个事情。这篇文章主要介绍了一个有趣的事情,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获,下面让小编带着大家一起了解一下。_运维学python该学些什么
文章浏览阅读524次。2019独角兽企业重金招聘Python工程师标准>>> ..._hotfix for msxml 4.0 service pack 2 - kb832414
文章浏览阅读546次。python和易语言的脚本哪门更实用?_易语言还是python适合辅助
文章浏览阅读134次。详解redis中的锁以及使用场景,指令,事务,分布式,命令,时间详解redis中的锁以及使用场景易采站长站,站长之家为您整理了详解redis中的锁以及使用场景的相关内容。分布式锁什么是分布式锁?分布式锁是控制分布式系统之间同步访问共享资源的一种方式。为什么要使用分布式锁? 为了保证共享资源的数据一致性。什么场景下使用分布式锁? 数据重要且要保证一致性如何实现分布式锁?主要介绍使用redis来实..._redis setnx watch