opencv4学习(57-67)

opencv4学习(57-67)
目录57.相机模型与投影58.单目相机标定59.图像校正60.单目位姿估计61.差值法检测移动物体62.稠密光流法跟踪移动物体63.稀疏光流法跟中移动物体64.监督学习聚类65.K均值聚类66.加载深度神经网络模型67.深度神经网络模型的使用57.相机模型与投影#include opencv2\opencv.hpp #include iostream #include vector using namespace std; using namespace cv; int main() { //输入计算得到的内参矩阵和畸变矩阵 Mat cameraMatrix (Mat_float(3, 3) 532.016297, 0, 332.172519, 0, 531.565159, 233.388075, 0, 0, 1); Mat distCoeffs (Mat_float(1, 5) -0.285188, 0.080097, 0.001274, -0.002415, 0.106579); //代码清单10-10中计算的第一张图像相机坐标系与世界坐标系之间的关系 Mat rvec (Mat_float(1, 3) -1.977853, -2.002220, 0.130029); Mat tvec (Mat_float(1, 3) -26.88155, -42.79936, 159.19703); //生成第一张图像中内角点的三维世界坐标 Size boardSize Size(9, 6); Size squareSize Size(10, 10); //棋盘格每个方格的真实尺寸 vectorPoint3f PointSets; for (int j 0; j boardSize.height; j) { for (int k 0; k boardSize.width; k) { Point3f realPoint; // 假设标定板为世界坐标系的z平面即z0 realPoint.x j*squareSize.width; realPoint.y k*squareSize.height; realPoint.z 0; PointSets.push_back(realPoint); } } //根据三维坐标和相机与世界坐标系时间的关系估计内角点像素坐标 vectorPoint2f imagePoints; projectPoints(PointSets, rvec, tvec, cameraMatrix, distCoeffs, imagePoints); for (int i 0; i imagePoints.size(); i) { cout 第 to_string(i) 个点的坐标 imagePoints[i] endl; } waitKey(0); return 0; }58.单目相机标定#include opencv2\opencv.hpp #include fstream #include iostream #include vector using namespace std; using namespace cv; int main() { //读取所有图像 vectorMat imgs; string imageName; ifstream fin(C:/opencv/calibdata.txt); while (getline(fin, imageName)) { Mat img imread(imageName); imgs.push_back(img); } Size board_size Size(9, 6); //方格标定板内角点数目行列 vectorvectorPoint2f imgsPoints; for (int i 0; i imgs.size(); i) { Mat img1 imgs[i]; Mat gray1; cvtColor(img1, gray1, COLOR_BGR2GRAY); vectorPoint2f img1_points; findChessboardCorners(gray1, board_size, img1_points); //计算方格标定板角点 find4QuadCornerSubpix(gray1, img1_points, Size(5, 5)); //细化方格标定板角点坐标 bool pattern true; drawChessboardCorners(img1, board_size, img1_points, pattern); imshow(img1, img1); waitKey(0); imgsPoints.push_back(img1_points); } //生成棋盘格每个内角点的空间三维坐标 Size squareSize Size(10, 10); //棋盘格每个方格的真实尺寸 vectorvectorPoint3f objectPoints; for (int i 0; i imgsPoints.size(); i) { vectorPoint3f tempPointSet; for (int j 0; j board_size.height; j) { for (int k 0; k board_size.width; k) { Point3f realPoint; // 假设标定板为世界坐标系的z平面即z0 realPoint.x j*squareSize.width; realPoint.y k*squareSize.height; realPoint.z 0; tempPointSet.push_back(realPoint); } } objectPoints.push_back(tempPointSet); } ///* 初始化每幅图像中的角点数量假定每幅图像中都可以看到完整的标定板 */ //vectorint point_number; //for (int i 0; iimgsPoints.size(); i) //{ // point_number.push_back(board_size.width*board_size.height); //} //图像尺寸 Size imageSize; imageSize.width imgs[0].cols; imageSize.height imgs[0].rows; Mat cameraMatrix Mat(3, 3, CV_32FC1, Scalar::all(0)); //摄像机内参数矩阵 Mat distCoeffs Mat(1, 5, CV_32FC1, Scalar::all(0)); //摄像机的5个畸变系数k1,k2,p1,p2,k3 vectorMat rvecs; //每幅图像的旋转向量 vectorMat tvecs; //每张图像的平移量 calibrateCamera(objectPoints, imgsPoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, 0); cout 相机的内参矩阵 endl cameraMatrix endl; cout 相机畸变系数 distCoeffs endl; waitKey(0); return 0; }59.图像校正#include opencv2\opencv.hpp #include iostream #include fstream #include vector using namespace std; using namespace cv; //用undistort()函数直接计算校正图像 void undist(vectorMat imgs, //所有原图像向量 Mat cameraMatrix, //计算得到的相机内参 Mat distCoeffs, //计算得到的相机畸变系数 vectorMat undistImgs) //校正后的输出图像 { for (int i 0; i imgs.size(); i) { Mat undistImg; undistort(imgs[i], undistImg, cameraMatrix, distCoeffs); undistImgs.push_back(undistImg); } } int main() { //读取所有图像 vectorMat imgs; string imageName; ifstream fin(C:/opencv/calibdata.txt); while (getline(fin, imageName)) { Mat img imread(imageName); imgs.push_back(img); } //输入前文计算得到的内参矩阵 Mat cameraMatrix (Mat_float(3, 3) 532.016297, 0, 332.172519, 0, 531.565159, 233.388075, 0, 0, 1); //输入前文计算得到的畸变矩阵 Mat distCoeffs (Mat_float(1, 5) -0.285188, 0.080097, 0.001274, -0.002415, 0.106579); vectorMat undistImgs; //Size imageSize; //imageSize.width imgs[0].cols; //imageSize.height imgs[0].rows; //用undistort()函数直接计算校正图像下一行代码取消注释即可 undist(imgs, cameraMatrix, distCoeffs, undistImgs); //显示校正前后的图像 for (int i 0; i imgs.size(); i) { string windowNumber to_string(i); imshow(未校正图像 windowNumber, imgs[i]); imshow(校正后图像 windowNumber, undistImgs[i]); waitKey(0); destroyWindow(未校正图像 windowNumber); destroyWindow(校正后图像 windowNumber); } waitKey(0); return 0; }60.单目位姿估计#include opencv2\opencv.hpp #include iostream #include vector using namespace std; using namespace cv; int main() { //读取所有图像 Mat img imread(C:/opencv/left01.jpg); Mat gray; cvtColor(img, gray, COLOR_BGR2GRAY); vectorPoint2f imgPoints; Size boardSize Size(9, 6); findChessboardCorners(gray, boardSize, imgPoints); //计算方格标定板角点 find4QuadCornerSubpix(gray, imgPoints, Size(5, 5)); //细化方格标定板角点坐标 //生成棋盘格每个内角点的空间三维坐标 Size squareSize Size(10, 10); //棋盘格每个方格的真实尺寸 vectorPoint3f PointSets; for (int j 0; j boardSize.height; j) { for (int k 0; k boardSize.width; k) { Point3f realPoint; // 假设标定板为世界坐标系的z平面即z0 realPoint.x j*squareSize.width; realPoint.y k*squareSize.height; realPoint.z 0; PointSets.push_back(realPoint); } } //输入前文计算得到的内参矩阵和畸变矩阵 Mat cameraMatrix (Mat_float(3, 3) 532.016297, 0, 332.172519, 0, 531.565159, 233.388075, 0, 0, 1); Mat distCoeffs (Mat_float(1, 5) -0.285188, 0.080097, 0.001274, -0.002415, 0.106579); //用PnP算法计算旋转和平移量 Mat rvec, tvec; solvePnP(PointSets, imgPoints, cameraMatrix, distCoeffs, rvec, tvec); cout 世界坐标系变换到相机坐标系的旋转向量 rvec endl; //旋转向量转换旋转矩阵 Mat R; Rodrigues(rvec, R); cout 旋转向量转换成旋转矩阵 endl R endl; //用PnPRansac算法计算旋转向量和平移向量 Mat rvecRansac, tvecRansac; solvePnPRansac(PointSets, imgPoints, cameraMatrix, distCoeffs, rvecRansac, tvecRansac); Mat RRansac; Rodrigues(rvecRansac, RRansac); cout 旋转向量转换成旋转矩阵 endl RRansac endl; waitKey(0); return 0; }61.差值法检测移动物体#include opencv2/opencv.hpp #includeiostream using namespace cv; using namespace std; int main() { //加载视频文件并判断是否加载成功 VideoCapture capture(C:/opencv/bike.avi); if (!capture.isOpened()) { cout 请确认视频文件是否正确 endl; return -1; } //输出视频相关信息 int fps capture.get(CAP_PROP_FPS); int width capture.get(CAP_PROP_FRAME_WIDTH); int height capture.get(CAP_PROP_FRAME_HEIGHT); int num_of_frames capture.get(CAP_PROP_FRAME_COUNT); cout 视频宽度 width 视频高度 height 视频帧率 fps 视频总帧数 num_of_frames endl; //读取视频中第一帧图像作为前一帧图像并进行灰度化 Mat preFrame, preGray; capture.read(preFrame); cvtColor(preFrame, preGray, COLOR_BGR2GRAY); //对图像进行高斯滤波减少噪声干扰 GaussianBlur(preGray, preGray, Size(0, 0), 15); Mat binary; Mat frame, gray; //形态学操作的矩形模板 Mat k getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1)); while (true) { //视频中所有图像处理完后推出循环 if (!capture.read(frame)) { break; } //对当前帧进行灰度化 cvtColor(frame, gray, COLOR_BGR2GRAY); GaussianBlur(gray, gray, Size(0, 0), 15); //计算当前帧与前一帧的差值的绝对值 absdiff(gray, preGray, binary); //对计算结果二值化并进行开运算减少噪声的干扰 threshold(binary, binary, 10, 255, THRESH_BINARY | THRESH_OTSU); morphologyEx(binary, binary, MORPH_OPEN, k); //显示处理结果 imshow(input, frame); imshow(result, binary); //将当前帧变成前一帧准备下一个循环注释掉这句话为固定背景 gray.copyTo(preGray); //5毫秒延时判断是否推出程序按ESC键退出 char c waitKey(5); if (c 27) { break; } } waitKey(0); return 0; }62.稠密光流法跟踪移动物体#include opencv2/opencv.hpp #include iostream using namespace cv; using namespace std; int main(int argc, char** argv) { VideoCapture capture(C:/opencv/vtest.avi); Mat prevFrame, prevGray; if (!capture.read(prevFrame)) { cout 请确认视频文件名称是否正确 endl; return -1; } //将彩色图像转换成灰度图像 cvtColor(prevFrame, prevGray, COLOR_BGR2GRAY); while (true) { Mat nextFrame, nextGray; //所有图像处理完成后推出程序 if (!capture.read(nextFrame)) { break; } imshow(视频图像, nextFrame); //计算稠密光流 cvtColor(nextFrame, nextGray, COLOR_BGR2GRAY); Mat_Point2f flow; //两个方向的运动速度 calcOpticalFlowFarneback(prevGray, nextGray, flow, 0.5, 3, 15, 3, 5, 1.2, 0); Mat xV Mat::zeros(prevFrame.size(), CV_32FC1); //x方向移动速度 Mat yV Mat::zeros(prevFrame.size(), CV_32FC1); //y方向移动速度 //提取两个方向的速度 for (int row 0; row flow.rows; row) { for (int col 0; col flow.cols; col) { const Point2f flow_xy flow.atPoint2f(row, col); xV.atfloat(row, col) flow_xy.x; yV.atfloat(row, col) flow_xy.y; } } //计算向量角度和幅值 Mat magnitude, angle; cartToPolar(xV, yV, magnitude, angle); //角度转换成角度制 angle angle * 180.0 / CV_PI / 2.0; //把幅值归一化到0-255区间便于显示结果 normalize(magnitude, magnitude, 0, 255, NORM_MINMAX); //计算角度和幅值的绝对值 convertScaleAbs(magnitude, magnitude); convertScaleAbs(angle, angle); //运动的幅值和角度生成HSV颜色空间的图像 Mat HSV Mat::zeros(prevFrame.size(), prevFrame.type()); vectorMat result; split(HSV, result); result[0] angle; //决定颜色 result[1] Scalar(255); result[2] magnitude; //决定形态 //将三个多通道图像合并成三通道图像 merge(result, HSV); //讲HSV颜色空间图像转换到RGB颜色空间中 Mat rgbImg; cvtColor(HSV, rgbImg, COLOR_HSV2BGR); //显示检测结果 imshow(运动检测结果, rgbImg); int ch waitKey(5); if (ch 27) { break; } } waitKey(0); return 0; }63.稀疏光流法跟中移动物体#include opencv2/opencv.hpp #include iostream using namespace cv; using namespace std; void draw_lines(Mat image, vectorPoint2f pt1, vectorPoint2f pt2); vectorScalar color_lut; //颜色查找表 int main() { VideoCapture capture(C:/opencv/mulballs.mp4); Mat prevframe, prevImg; if (!capture.read(prevframe)) { cout 请确认输入视频文件是否正确 endl; return -1; } cvtColor(prevframe, prevImg, COLOR_BGR2GRAY); //角点检测相关参数设置 vectorPoint2f Points; double qualityLevel 0.01; int minDistance 10; int blockSize 3; bool useHarrisDetector false; double k 0.04; int Corners 5000; //角点检测 goodFeaturesToTrack(prevImg, Points, Corners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k); //稀疏光流检测相关参数设置 vectorPoint2f prevPts; //前一帧图像角点坐标 vectorPoint2f nextPts; //当前帧图像角点坐标 vectoruchar status; //检点检测到的状态 vectorfloat err; TermCriteria criteria TermCriteria(TermCriteria::COUNT TermCriteria::EPS, 30, 0.01); double derivlambda 0.5; int flags 0; //初始状态的角点 vectorPoint2f initPoints; initPoints.insert(initPoints.end(), Points.begin(), Points.end()); //前一帧图像中的角点坐标 prevPts.insert(prevPts.end(), Points.begin(), Points.end()); while (true) { Mat nextframe, nextImg; if (!capture.read(nextframe)) { break; } imshow(nextframe, nextframe); //光流跟踪 cvtColor(nextframe, nextImg, COLOR_BGR2GRAY); calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err, Size(31, 31), 3, criteria, derivlambda, flags); //判断角点是否移动如果不移动就删除 size_t i, k; for (i k 0; i nextPts.size(); i) { // 距离与状态测量 double dist abs(prevPts[i].x - nextPts[i].x) abs(prevPts[i].y - nextPts[i].y); if (status[i] dist 2) { prevPts[k] prevPts[i]; initPoints[k] initPoints[i]; nextPts[k] nextPts[i]; circle(nextframe, nextPts[i], 3, Scalar(0, 255, 0), -1, 8); } } //更新移动角点数目 nextPts.resize(k); prevPts.resize(k); initPoints.resize(k); // 绘制跟踪轨迹 draw_lines(nextframe, initPoints, nextPts); imshow(result, nextframe); char c waitKey(50); if (c 27) { break; } //更新角点坐标和前一帧图像 std::swap(nextPts, prevPts); nextImg.copyTo(prevImg); //如果角点数目少于30就重新检测角点 if (initPoints.size() 30) { goodFeaturesToTrack(prevImg, Points, Corners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k); initPoints.insert(initPoints.end(), Points.begin(), Points.end()); prevPts.insert(prevPts.end(), Points.begin(), Points.end()); printf(total feature points : %d\n, prevPts.size()); } } return 0; } void draw_lines(Mat image, vectorPoint2f pt1, vectorPoint2f pt2) { RNG rng(5000); if (color_lut.size() pt1.size()) { for (size_t t 0; t pt1.size(); t) { color_lut.push_back(Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255))); } } for (size_t t 0; t pt1.size(); t) { line(image, pt1[t], pt2[t], color_lut[t], 2, 8, 0); } }64.监督学习聚类#include opencv2/opencv.hpp #include iostream using namespace cv; using namespace cv::ml; using namespace std; int main(int argc, char** argv) { Mat img imread(C:/opencv/digits.png); Mat gray; cvtColor(img, gray, COLOR_BGR2GRAY); // 分割为5000个cells Mat images Mat::zeros(5000, 400, CV_8UC1); Mat labels Mat::zeros(5000, 1, CV_8UC1); int index 0; Rect numberImg; numberImg.x 0; numberImg.height 1; numberImg.width 400; for (int row 0; row 50; row) { //从图像中分割出20×20的图像作为独立数字图像 int label row / 5; int datay row * 20; for (int col 0; col 100; col) { int datax col * 20; Mat number Mat::zeros(Size(20, 20), CV_8UC1); for (int x 0; x 20; x) { for (int y 0; y 20; y) { number.atuchar(x, y) gray.atuchar(x datay, y datax); } } //将二维图像数据转成行数据 Mat row number.reshape(1, 1); cout 提取第 index 1 个数据 endl; numberImg.y index; //添加到总数据中 row.copyTo(images(numberImg)); //记录每个图像对应的数字标签 labels.atuchar(index, 0) label; index; } } imwrite(C:/opencv/所有数据按行排列结果.png, images); imwrite(C:/opencv/标签.png, labels); //加载训练数据集 images.convertTo(images, CV_32FC1); labels.convertTo(labels, CV_32SC1); Ptrml::TrainData tdata ml::TrainData::create(images, ml::ROW_SAMPLE, labels); //创建K近邻类 PtrKNearest knn KNearest::create(); knn-setDefaultK(5); //每个类别拿出5个数据 knn-setIsClassifier(true); //进行分类 //训练数据 knn-train(tdata); //保存训练结果 knn-save(C:/opencv/knn_model.yml); //输出运行结果提示 cout 已使用K近邻完成数据训练和保存 endl; waitKey(0); return true; }#include opencv2/opencv.hpp #include iostream using namespace cv; using namespace cv::ml; using namespace std; int main() { system(color F0); // 加载KNN分类器 Mat data imread(C:/opencv/所有数据按行排列结果.png, IMREAD_ANYDEPTH); Mat labels imread(C:/opencv/标签.png, IMREAD_ANYDEPTH); data.convertTo(data, CV_32FC1); labels.convertTo(labels, CV_32SC1); PtrKNearest knn Algorithm::loadKNearest(C:/opencv/knn_model.yml); //查看分类结果 Mat result; knn-findNearest(data, 5, result); //统计分类结果与真实结果相同的数目 int count 0; for (int row 0; row result.rows; row) { int predict result.atfloat(row, 0); if (labels.atint(row, 0) predict) { count count 1; } } float rate 1.0*count / result.rows; cout 分类的正确性 rate endl; //测试新图像是否能够识别数字 Mat testImg1 imread(C:/opencv/handWrite01.png, IMREAD_GRAYSCALE); Mat testImg2 imread(C:/opencv/handWrite02.png, IMREAD_GRAYSCALE); imshow(testImg1, testImg1); imshow(testImg2, testImg2); //缩放到20×20的尺寸 resize(testImg1, testImg1, Size(20, 20)); resize(testImg2, testImg2, Size(20, 20)); Mat testdata Mat::zeros(2, 400, CV_8UC1); Rect rect; rect.x 0; rect.y 0; rect.height 1; rect.width 400; Mat oneDate testImg1.reshape(1, 1); Mat twoData testImg2.reshape(1, 1); oneDate.copyTo(testdata(rect)); rect.y 1; twoData.copyTo(testdata(rect)); //数据类型转换 testdata.convertTo(testdata, CV_32F); //进行估计识别 Mat result2; knn-findNearest(testdata, 5, result2); //查看预测的结果 for (int i 0; i result2.rows; i) { int predict result2.atfloat(i, 0); cout 第 i 1 图像预测结果 predict 真实结果 i 1 endl; } waitKey(0); return 0; }#include opencv2/opencv.hpp #include iostream using namespace std; using namespace cv; using namespace cv::ml; int main() { //训练数据 Mat samples, labls; FileStorage fread(C:/opencv/point.yml, FileStorage::READ); fread[data] samples; fread[labls] labls; fread.release(); //不同种类坐标点拥有不同的颜色 vectorVec3b colors; colors.push_back(Vec3b(0, 255, 0)); colors.push_back(Vec3b(0, 0, 255)); //创建空白图像用于显示坐标点 Mat img(480, 640, CV_8UC3, Scalar(255, 255, 255)); Mat img2; img.copyTo(img2); //在空白图像中绘制坐标点 for (int i 0; i samples.rows; i) { Point2f point; point.x samples.atfloat(i, 0); point.y samples.atfloat(i, 1); Scalar color colors[labls.atint(i, 0)]; circle(img, point, 3, color, -1); circle(img2, point, 3, color, -1); } imshow(两类像素点图像, img); //建立模型 PtrSVM model SVM::create(); //参数设置 model-setKernel(SVM::INTER); //内核的模型 model-setType(SVM::C_SVC); //SVM的类型 model-setTermCriteria(TermCriteria(TermCriteria::MAX_ITER TermCriteria::EPS, 100, 0.01)); //model-setGamma(5.383); //model-setC(0.01); //model-setDegree(3); //训练模型 model-train(TrainData::create(samples, ROW_SAMPLE, labls)); //用模型对图像中全部像素点进行分类 Mat imagePoint(1, 2, CV_32FC1); for (int y 0; y img2.rows; y y 2) { for (int x 0; x img2.cols; x x 2) { imagePoint.atfloat(0) (float)x; imagePoint.atfloat(1) (float)y; int color (int)model-predict(imagePoint); img2.atVec3b(y, x) colors[color]; } } imshow(图像所有像素点分类结果, img2); waitKey(); return 0; }65.K均值聚类#include opencv2/opencv.hpp #include iostream using namespace cv; using namespace std; int main() { //生成一个500×500的图像用于显示特征点和分类结果 Mat img(500, 500, CV_8UC3, Scalar(255, 255, 255)); RNG rng(10000); //设置三种颜色 Scalar colorLut[3] { Scalar(0, 0, 255), Scalar(0, 255, 0), Scalar(255, 0, 0), }; //设置三个点集并且每个点集中点的数目随机 int number 3; int Points1 rng.uniform(20, 200); int Points2 rng.uniform(20, 200); int Points3 rng.uniform(20, 200); int Points_num Points1 Points2 Points3; Mat Points(Points_num, 1, CV_32FC2); int i 0; for (; i Points1; i) { Point2f pts; pts.x rng.uniform(100, 200); pts.y rng.uniform(100, 200); Points.atPoint2f(i, 0) pts; } for (; i Points1 Points2; i) { Point2f pts; pts.x rng.uniform(300, 400); pts.y rng.uniform(100, 300); Points.atPoint2f(i, 0) pts; } for (; i Points1 Points2 Points3; i) { Point2f pts; pts.x rng.uniform(100, 200); pts.y rng.uniform(390, 490); Points.atPoint2f(i, 0) pts; } // 使用KMeans Mat labels; //每个点所属的种类 Mat centers; //每类点的中心位置坐标 kmeans(Points, number, labels, TermCriteria(TermCriteria::EPS TermCriteria::COUNT, 10, 0.1), 3, KMEANS_PP_CENTERS, centers); // 根据分类为每个点设置不同的颜色 img Scalar::all(255); for (int i 0; i Points_num; i) { int index labels.atint(i); Point point Points.atPoint2f(i); circle(img, point, 2, colorLut[index], -1, 4); } // 绘制每个聚类的中心来绘制圆 for (int i 0; i centers.rows; i) { int x centers.atfloat(i, 0); int y centers.atfloat(i, 1); cout 第 i 1 类的中心坐标x x y y endl; circle(img, Point(x, y), 50, colorLut[i], 1, LINE_AA); } imshow(K均值聚类分类结果, img); waitKey(0); Mat img2 imread(C:/opencv/people.jpg); if (!img2.data) { printf(请确认图像文件是否输入正确); return -1; } Vec3b colorLut2[5] { Vec3b(0, 0, 255), Vec3b(0, 255, 0), Vec3b(255, 0, 0), Vec3b(0, 255, 255), Vec3b(255, 0, 255) }; //图像的尺寸用于计算图像中像素点的数目 int width img2.cols; int height img2.rows; // 初始化定义 int sampleCount width*height; //将图像矩阵数据转换成每行一个数据的形式 Mat sample_data img2.reshape(3, sampleCount); Mat data; sample_data.convertTo(data, CV_32F); //KMean函数将像素值进行分类 int number2 3; //分割后的颜色种类 Mat labels2; TermCriteria criteria TermCriteria(TermCriteria::EPS TermCriteria::COUNT, 10, 0.1); kmeans(data, number2, labels2, criteria, number2, KMEANS_PP_CENTERS); // 显示图像分割结果 Mat result Mat::zeros(img2.size(), img2.type()); for (int row 0; row height; row) { for (int col 0; col width; col) { int index row*width col; int label labels2.atint(index, 0); result.atVec3b(row, col) colorLut2[label]; } } namedWindow(原图, WINDOW_NORMAL); imshow(原图, img2); namedWindow(分割后图像, WINDOW_NORMAL); imshow(分割后图像, result); waitKey(0); return 0; }66.加载深度神经网络模型#include opencv2/opencv.hpp #include iostream using namespace cv; using namespace cv::dnn; using namespace std; int main() { // 设置控制台白底黑字仅Windows生效 system(color F0); // Caffe模型两个配套文件权重 网络结构 string model C:/opencv/bvlc_googlenet.caffemodel; string config C:/opencv/bvlc_googlenet.prototxt; // 加载Caffe神经网络 Net net dnn::readNet(model, config); if (net.empty()) { cout 请确认模型文件路径是否正确文件是否存在 endl; return -1; } // 获取网络全部层的名称列表 vectorString layerNames net.getLayerNames(); // 循环遍历每一层 for (int i 0; i layerNames.size(); i) { // 根据层名获取层唯一ID int ID net.getLayerId(layerNames[i]); // 根据ID获取层完整对象读取层类型等信息 PtrLayer layer net.getLayer(ID); // 打印层ID、层名称、层算子类型Conv/ReLU/Pool等 cout 网络层数ID ID 网络层名称 layerNames[i] endl 网络层类型 layer-type.c_str() endl endl; } return 0; }67.深度神经网络模型的使用#include opencv2/opencv.hpp #include iostream #include fstream using namespace cv; using namespace cv::dnn; using namespace std; int main() { Mat img imread(C:/opencv/airplane.jpg); if (img.empty()) { printf(could not load image...\n); return -1; } //读取分类种类名称 String typeListFile C:/opencv/image_recognition/imagenet_comp_graph_label_strings.txt; vectorString typeList; ifstream file(typeListFile); if (!file.is_open()) { printf(请确认分类种类名称是否正确); return -1; } std::string type; while (!file.eof()) { //读取名称 getline(file, type); if (type.length()) typeList.push_back(type); } file.close(); // 加载网络 String tf_pb_file C:/opencv/image_recognition/tensorflow_inception_graph.pb; Net net readNet(tf_pb_file); if (net.empty()) { printf(请确认模型文件是否为空文件); return -1; } //对输入图像数据进行处理 Mat blob blobFromImage(img, 1.0f, Size(224, 224), Scalar(), true, false); //进行图像种类预测 Mat prob; net.setInput(blob, input); prob net.forward(softmax2); // 得到最可能分类输出 Mat probMat prob.reshape(1, 1); Point classNumber; double classProb; //最大可能性 minMaxLoc(probMat, NULL, classProb, NULL, classNumber); string typeName typeList.at(classNumber.x).c_str(); cout 图像中物体可能为 typeName 可能性为 classProb; //检测内容 string str typeName possibility: to_string(classProb); putText(img, str, Point(50, 50), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 0, 255), 2, 8); imshow(图像判断结果, img); waitKey(0); return 0; }#include opencv2/opencv.hpp #include iostream using namespace cv; using namespace cv::dnn; using namespace std; int main() { Mat image imread(C:/opencv/lena.png); String models[5] { the_wave.t7, mosaic.t7, feathers.t7, candy.t7, udnie.t7 }; for (int i 0; i size(models); i) { Net net readNet(C:/opencv/fast_style/ models[i]); imshow(原始图像, image); //计算图像每个通道的均值 Scalar imgaeMean mean(image); //调整图像尺寸和格式 Mat blobImage blobFromImage(image, 1.0, Size(256, 256), imgaeMean, false, false); //计算网络对原图像处理结果 net.setInput(blobImage); Mat output net.forward(); //输出结果的尺寸和通道数 int outputChannels output.size[1]; int outputRows output.size[2]; int outputCols output.size[3]; //将输出结果存放到图像中 Mat result Mat::zeros(Size(outputCols, outputRows), CV_32FC3); float* data output.ptrfloat(); for (int channel 0; channel outputChannels; channel) { for (int row 0; row outputRows; row) { for (int col 0; col outputCols; col) { result.atVec3f(row, col)[channel] *data; } } } //对迁移结果进行进一步操作处理 //恢复图像减掉的均值 result result imgaeMean; //对图像进行归一化便于图像显示 result result / 255.0; //调整图像尺寸使得与原图像尺寸相同 resize(result, result, image.size()); //显示结果 imshow(第 to_string(i) 种风格迁移结果, result); } waitKey(0); return 0; }#include opencv2/opencv.hpp #include opencv2/dnn.hpp #include iostream using namespace cv; using namespace cv::dnn; using namespace std; int main() { Mat img imread(C:/opencv/faces.jpg); if (img.empty()) { cout 请确定是否输入正确的图像文件 endl; return -1; } //读取人脸识别模型 String model_bin C:/opencv/face_age/opencv_face_detector_uint8.pb; String config_text C:/opencv/face_age/opencv_face_detector.pbtxt; Net faceNet readNet(model_bin, config_text); //读取性别检测模型 String genderProto C:/opencv/face_age/gender_deploy.prototxt; String genderModel C:/opencv/face_age/gender_net.caffemodel; String genderList[] { Male, Female }; Net genderNet readNet(genderModel, genderProto); if (faceNet.empty() genderNet.empty()) { cout 请确定是否输入正确的模型文件 endl; return -1; } //对整幅图像进行人脸检测 Mat blobImage blobFromImage(img, 1.0, Size(300, 300), Scalar(), false, false); faceNet.setInput(blobImage, data); Mat detect faceNet.forward(detection_out); //人脸概率、人脸矩形区域的位置 Mat detectionMat(detect.size[2], detect.size[3], CV_32F, detect.ptrfloat()); //对每个人脸区域进行性别检测 int exBoundray 25; //每个人脸区域四个方向扩充的尺寸 float confidenceThreshold 0.5; //判定为人脸的概率阈值阈值越大准确性越高 for (int i 0; i detectionMat.rows; i) { float confidence detectionMat.atfloat(i, 2); //检测为人脸的概率 //只检测概率大于阈值区域的性别 if (confidence confidenceThreshold) { //网络检测人脸区域大小 int topLx detectionMat.atfloat(i, 3) * img.cols; int topLy detectionMat.atfloat(i, 4) * img.rows; int bottomRx detectionMat.atfloat(i, 5) * img.cols; int bottomRy detectionMat.atfloat(i, 6) * img.rows; Rect faceRect(topLx, topLy, bottomRx - topLx, bottomRy - topLy); //将网络检测出的区域尺寸进行扩充要注意防止尺寸在图像真实尺寸之外 Rect faceTextRect; faceTextRect.x max(0, faceRect.x - exBoundray); faceTextRect.y max(0, faceRect.y - exBoundray); faceTextRect.width min(faceRect.width exBoundray, img.cols - 1); faceTextRect.height min(faceRect.height exBoundray, img.rows - 1); Mat face img(faceTextRect); //扩充后的人脸图像 //调整面部图像尺寸 Mat faceblob blobFromImage(face, 1.0, Size(227, 227), Scalar(), false, false); //将调整后的面部图像输入到性别检测网络 genderNet.setInput(faceblob); //计算检测结果 Mat genderPreds genderNet.forward(); //两个性别的可能性 //性别检测结果 float male, female; male genderPreds.atfloat(0, 0); female genderPreds.atfloat(0, 1); int classID male female ? 0 : 1; String gender genderList[classID]; //在原图像中绘制面部轮廓和性别 rectangle(img, faceRect, Scalar(0, 0, 255), 2, 8, 0); putText(img, gender.c_str(), faceRect.tl(), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 0, 255), 2, 8); } } imshow(性别检测结果, img); waitKey(0); return 0; }

最新新闻

日新闻

周新闻

月新闻