【opencv】教程代码 —ShapeDescriptors
检测和显示图像的轮廓
在图像中搜索并显示轮廓边缘多边形、轮廓矩形和包围圆
获取包含检测到的轮廓的椭圆和旋转的矩形
图像轮廓检测和轮廓凸包
计算图像中的轮廓的矩(包括面积、重心等)并进行显示
创建和绘制一个多边形图像然后计算并显示图像上每个点到这个多边形的距离
1. findContours_demo.cpp 检测和显示图像的轮廓
这段代码是使用OpenCV库来检测和显示图像的轮廓。这段代码中包含两个主要函数:main函数和thresh_callback函数。
1. main函数用于加载图像,将其转换为灰度图像并对其进行模糊处理,然后在窗口中显示原始图像并创建一个滑块来调整Canny边缘检测的阈值。主要步骤如下:
加载图像:使用OpenCV函数imread加载图像。
转换图像:使用cvtColor函数将图像从BGR色彩空间转换为灰度空间。之后,使用blur函数对图像进行模糊处理以消除噪声。
创建并显示窗口:使用namedWindow和imshow函数创建窗口并显示源图像。
创建滑块:使用createTrackbar函数创建一个滑块来调整边缘检测的阈值。
调用thresh_callback函数。
2. thresh_callback函数用于边缘检测,找到并绘制轮廓。主要步骤如下:
边缘检测:通过Canny函数检测边缘。
找到轮廓:使用findContours函数找到图像中的轮廓。
绘制轮廓:初始化一个与原图大小、类型相同的全零矩阵。然后在该矩阵上绘制找到的轮廓。每个轮廓有不同的颜色。
显示窗口:调用imshow函数显示绘制过的轮廓图像。
最后,代码中还编写了一些错误处理机制,例如,如果找不到图像,则返回-1并退出程序。
/*** @function findContours_Demo.cpp* @brief 这是一个演示如何在图像中找到轮廓的示例代码* @author OpenCV团队*/#include "opencv2/imgcodecs.hpp" // 引入opencv图像编解码库
#include "opencv2/highgui.hpp" // 引入opencv高级GUI库
#include "opencv2/imgproc.hpp" // 引入opencv图像处理库
#include <iostream> // 引入标准输入输出库using namespace cv; // 使用cv命名空间,该命名空间包含所有OpenCV函数和类
using namespace std; // 使用std命名空间,该命名空间包含所有标准C++库函数和类Mat src_gray; // 声明全局变量src_gray,用于存储灰度图像
int thresh = 100; // 声明全局变量thresh,设定轮廓检测的阈值
RNG rng(12345); // 初始化随机数生成器/// 函数声明
void thresh_callback(int, void* );/*** @function main*/
int main( int argc, char** argv ) // 主函数
{/// 加载源图像CommandLineParser parser( argc, argv, "{@input | HappyFish.jpg | input image}" ); // 创建命令行解析器,解析输入的图像文件路径Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) ); // 读取图像文件if( src.empty() ) // 如果读取的图像为空{cout << "Could not open or find the image!\n" << endl; // 输出错误信息cout << "Usage: " << argv[0] << " <Input image>" << endl; // 输出正确的使用方法return -1;}/// 将图像转换为灰度图并进行模糊处理cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 将图像转换为灰度图blur( src_gray, src_gray, Size(3,3) ); // 对图像进行模糊处理,减少噪声/// 创建窗口const char* source_window = "Source"; // 源图像窗口的名称namedWindow( source_window ); // 创建源图像窗口imshow( source_window, src ); // 显示源图像const int max_thresh = 255; // 设定最大阈值createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback ); // 创建滑动条,调节Canny检测器的阈值thresh_callback( 0, 0 ); // 调用thresh_callback函数,进行轮廓检测waitKey(); // 等待用户按键,以便可以看到图像return 0;
}/*** @function thresh_callback* 轮廓检测回调函数*/
void thresh_callback(int, void* )
{/// 使用Canny算子检测边缘Mat canny_output; // 声明变量,存储Canny检测结果Canny( src_gray, canny_output, thresh, thresh*2 ); // 运用Canny算子进行边缘检测/// 查找轮廓vector<vector<Point> > contours; // 存储找到的轮廓vector<Vec4i> hierarchy; // 存储轮廓的层级信息findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE ); // 查找轮廓/// 绘制轮廓Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 ); // 创建空白画布,用来绘制轮廓for( size_t i = 0; i< contours.size(); i++ ) // 遍历找到的所有轮廓{Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) ); // 生成随机颜色drawContours( drawing, contours, (int)i, color, 2, LINE_8, hierarchy, 0 ); // 在drawing上绘制轮廓}/// 显示在窗口中imshow( "Contours", drawing ); // 显示绘制轮廓后的画面
}
这段代码主要功能是载入一个图像进行灰度和模糊处理,然后使用Canny算子进行边缘检测,并找出图像的轮廓,最后将轮廓在窗口中显示出来。图像的路径可以通过命令行参数传入,如果没有参数则默认加载名为"HappyFish.jpg"的图像。在检测轮廓的过程中,可以通过滑动条实时调整Canny算子的阈值,以达到最佳的轮廓检测效果。
2. generalContours_demo1.cpp在图像中搜索并显示轮廓边缘多边形、轮廓矩形和包围圆
这段代码主要用于在图像中寻找轮廓。作者使用OpenCV库编写了代码。下面是我对您提供的代码片段的详细解析和总结:
整个代码中包含两个主要函数:"main" 和 "thresh_callback"。
"main" 函数:
该函数的主要任务是加载图片,将图片转换为灰度图像,模糊处理,并创建窗口显示源图像。接着创建了一个滑条用于调节阈值。完成以上设置后,程序将调用“thresh_callback”回调函数处理边缘检测和轮廓提取。最后,通过waitKey()函数等待用户按键操作。
关键过程如下:
- 加载图像: 使用imread函数读取输入的图像文件。
- 灰度转换: 调用cvtColor函数将RGB图像转化为灰度图像。
- 模糊处理: 使用blur函数对灰度图像进行模糊处理,以去除图像中的噪声。
- 显示窗口: 使用namedWindow创建一个图像窗口,imshow在该窗口中显示源图像。
- 创建滑条: 使用createTrackbar函数创建了滑动条,可以调节Canny边缘检测阈值。
"thresh_callback" 函数:
这个函数执行的主要任务是使用Canny算法进行边缘检测,接着找到图像的轮廓。最后,通过绘制多边形轮廓,包围矩形和圆,将处理后的图像显示在窗口中。
关键过程如下:
- 边缘检测: 调用Canny函数对图像进行边缘检测,生成边缘图像。
- 轮廓提取: 使用findContours函数在二值化图像canny_output中寻找轮廓。
- 对轮廓进行处理: 利用approxPolyDP将轮廓近似为多边形,使用boundingRect获取轮廓的最小外接矩形,使用minEnclosingCircle获取轮廓的最小外接圆。
- 绘制结果:绘制所有的包围矩形,圆和对应的多边形轮廓到图像上。
- 结果展示: 使用imshow函数在窗口中展示处理结果。
/*** @function generalContours_demo1.cpp* @brief Demo code to find contours in an image(用于在图片中找到轮廓的演示代码)* @author OpenCV team (OpenCV团队)*/#include "opencv2/imgcodecs.hpp" // 引入处理图像编码的头文件
#include "opencv2/highgui.hpp" // 引入GUI的头文件
#include "opencv2/imgproc.hpp" // 引入处理图像的头文件
#include <iostream> // 引入基础输入输出流的头文件using namespace cv; // 使用cv命名空间
using namespace std; // 使用std命名空间Mat src_gray; // 声明灰度图像对象
int thresh = 100; // 设置阈值
RNG rng(12345); // 初始化随机数生成器/// Function header
void thresh_callback(int, void* );// 声明阈值处理函数/*** @function main*/
int main( int argc, char** argv ) // 主函数开始
{/// Load source image (加载源图片)CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( src.empty() ) // 如果无法加载图片,则输出错误信息并返回-1退出程序{cout << "Could not open or find the image!\n" << endl;cout << "usage: " << argv[0] << " <Input image>" << endl;return -1;}/// Convert image to gray and blur it (将图片转为灰度并进行模糊处理)cvtColor( src, src_gray, COLOR_BGR2GRAY ); // BGR转换成灰度blur( src_gray, src_gray, Size(3,3) ); // 对灰度图进行模糊处理/// Create Window (创建窗口)const char* source_window = "Source";namedWindow( source_window );imshow( source_window, src ); // 展示原图/// Create Trackbar (创建滑动条)const int max_thresh = 255;createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 ); // 调用阈值处理函数waitKey(); // 等待用户操作return 0; // 程序正常退出
}/*** @function thresh_callback*/
void thresh_callback(int, void* ) // 阈值处理函数定义
{/// Detect edges using Canny (使用Canny算法进行边缘检测)Mat canny_output; Canny( src_gray, canny_output, thresh, thresh*2 ); /// Find contours (查找轮廓)vector<vector<Point> > contours;findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE ); /// Approximate contours to polygons + get bounding rects and circles (将轮廓近似为多边形,并找到它们的边界矩形和圆)vector<vector<Point> > contours_poly( contours.size() ); // 用于存储多边形轮廓的向量vector<Rect> boundRect( contours.size() ); // 用于存储边界矩形的向量vector<Point2f>centers( contours.size() ); // 用于存储圆心的向量vector<float>radius( contours.size() ); // 用于存储半径的向量for( size_t i = 0; i < contours.size(); i++ ) // 遍历每一个轮廓{approxPolyDP( contours[i], contours_poly[i], 3, true ); // 近似多边形boundRect[i] = boundingRect( contours_poly[i] ); // 计算边界矩形minEnclosingCircle( contours_poly[i], centers[i], radius[i] ); // 计算最小闭合圆}Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 ); // 创建一个全零矩阵,用于绘制结果图/// Draw polygonal contour + bonding rects + circles (绘制多边形轮廓、边界矩形和圆)for( size_t i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) ); //生成随机颜色drawContours( drawing, contours_poly, (int)i, color ); // 绘制轮廓rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2 ); // 绘制矩形circle( drawing, centers[i], (int)radius[i], color, 2 ); // 绘制圆}/// Show in a window (显示结果图)imshow( "Contours", drawing ); // 显示轮廓图
}
这段代码是一个在图像中搜索并显示轮廓的OpenCV程序,它首先将给定图像转换为灰度图像,然后使用Canny算法检测其边缘,进而使用函数findContours
查找这些边缘。找到的边缘以多边形形式近似,并计算其边界矩形和包围圆。最后,所有的轮廓、边框矩形和包围圆都绘制在一张空白图像上并显示出来。
3. generalContours_demo2.cpp 获取包含检测到的轮廓的椭圆和旋转的矩形
这段代码是一个OpenCV的演示程序,用于获取包含检测到的轮廓的椭圆和旋转的矩形。主要包含以下函数:
thresh_callback
: 该函数用于检测边缘及寻找轮廓,并通过minAreaRect
和fitEllipse
方法获取每个轮廓的旋转矩阵和椭圆,然后绘制轮廓、椭圆和旋转矩形。main
: 该函数用于加载源图像并转换为灰度图,然后进行模糊处理,最后创建一个窗口并在其中显示源图像。还在窗口中创建了一个跟踪条,用于调整Canny算法的阈值参数。
具体来讲,我来详细解释下这两个函数的工作流程与方法:
main
: 首先加载输入的图像,并将其转换为灰度图像,然后对该灰度图像进行模糊处理。然后创建一个窗口在其中显示转换后的图像,并在这个窗口中创建一个跟踪条,来调整使用Canny方法进行边缘检测的阈值。在跟踪条的回调函数中,调用了thresh_callback
方法进行边缘检测和轮廓寻找。thresh_callback
: 在这个函数中,首先使用Canny方法进行边缘检测。然后使用findContours
方法寻找图像的轮廓。接着使用minAreaRect
方法获取每个轮廓的最小面积旋转矩形,如果轮廓的点数大于5,则使用fitEllipse
方法获取该轮廓的拟合椭圆。然后创建一个全零的Mat对象,然后在这个Mat对象上绘制轮廓、椭圆及旋转矩形。最后将这个Mat对象在窗口中显示。
该程序主要用于练习边缘检测、寻找轮廓以及如何在寻找到的轮廓上拟合旋转矩形和椭圆。
/**
* @function generalContours_demo2.cpp
* @brief 这是一个演示代码,用于获取包含检测到的轮廓的椭圆和旋转矩形
* @author OpenCV 团队
*/ #include "opencv2/imgcodecs.hpp" // 包括OpenCV的读写头文件
#include "opencv2/highgui.hpp" // 包括OpenCV的GUI头文件
#include "opencv2/imgproc.hpp" // 包括OpenCV的图像处理头文件
#include <iostream> // 包括输入输出流头文件using namespace cv; // 声明使用OpenCV的命名空间
using namespace std; // 声明使用标准模板库命名空间Mat src_gray; // 创建一个空的Mat对象,用于存放灰度图像
int thresh = 100; // 设定初始阈值为100
RNG rng(12345); // 创建一个随机数生成器对象/// 函数声明
void thresh_callback(int, void* );/*** @function main*/
int main( int argc, char** argv )
{/// 加载源图像并转化为灰度 CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( src.empty() ) // 检查读取的图像是否为空{cout << "Could not open or find the image!\n" << endl; // 输出错误信息cout << "Usage: " << argv[0] << " <Input image>" << endl; // 提示正确的使用方式return -1;}/// 将图像转化为灰度图并模糊处理cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 将图像从BGR色彩空间转化为灰度空间blur( src_gray, src_gray, Size(3,3) ); // 对图像进行模糊(平滑)处理/// 创建窗口 const char* source_window = "Source";namedWindow( source_window );imshow( source_window, src );const int max_thresh = 255; // 设定阈值调节的最大值createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );thresh_callback( 0, 0 );waitKey(); // 等待键盘操作return 0;
}/*** @function thresh_callback*/
void thresh_callback(int, void* )
{/// 用Canny算子进行边缘检测Mat canny_output;Canny( src_gray, canny_output, thresh, thresh*2 );/// 找到轮廓vector<vector<Point> > contours;findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );/// 计算每个轮廓对应的旋转矩形和椭圆形状vector<RotatedRect> minRect( contours.size() ); // 创建一个旋转矩形的向量,数量等于轮廓数量vector<RotatedRect> minEllipse( contours.size() ); // 创建一个轮廓对应椭圆的向量,数量等于轮廓数量for( size_t i = 0; i < contours.size(); i++ ) // 遍历每一个轮廓{minRect[i] = minAreaRect( contours[i] ); // 计算每个轮廓的最小区域旋转矩形if( contours[i].size() > 5 ) // 当轮廓包含的点多于5个时,即可以拟合为椭圆{minEllipse[i] = fitEllipse( contours[i] ); // 计算每个轮廓的拟合椭圆}}/// 画出轮廓 + 旋转矩形 + 椭圆Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 ); // 创建一个空白画布,尺寸与canny_output相同for( size_t i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) ); // 生成一个随机颜色// 画出轮廓drawContours( drawing, contours, (int)i, color );// 画出椭圆ellipse( drawing, minEllipse[i], color, 2 );// 画出旋转矩形Point2f rect_points[4];minRect[i].points( rect_points );for ( int j = 0; j < 4; j++ ){line( drawing, rect_points[j], rect_points[(j+1)%4], color );}}/// 在窗口中展示结果 imshow( "Contours", drawing );
}
此代码段是一个 OpenCV 的示例,演示了如何查找图像中的所有轮廓并查找每个轮廓的最小区域旋转矩形和拟合椭圆。在迭代访问每个轮廓的过程中,根据轮廓大小检查是否可以拟合椭圆(轮廓中的点数大于5)。最后,它会在新创建的 Mat 对象上绘制轮廓、旋转的矩形和椭圆,然后在窗口中显示这个 Mat 对象。
4. hull_demo.cpp 图像轮廓检测和轮廓凸包
/*** @function hull_demo.cpp // 声明hull_demo.cpp这个函数* @brief Demo code to find contours in an image // 对图像进行轮廓检测的演示代码* @author OpenCV team // 作者为OpenCV团队*/#include "opencv2/imgcodecs.hpp" // 导入编解码库
#include "opencv2/highgui.hpp" // 导入高级GUI库
#include "opencv2/imgproc.hpp" // 导入图像处理库
#include <iostream> // 导入输入输出库using namespace cv;
using namespace std;Mat src_gray; // 定义源图像的灰度图
int thresh = 100; // 定义阈值为100
RNG rng(12345); // 定义一个随机数/// Function header
void thresh_callback(int, void* ); // 声明一个阈值回调函数/*** @function main // 主函数*/
int main( int argc, char** argv )
{/// Load source image and convert it to gray // 加载源图像并转化为灰度图CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( src.empty() ){cout << "Could not open or find the image!\n" << endl;cout << "Usage: " << argv[0] << " <Input image>" << endl;return -1;}/// Convert image to gray and blur it // 将图像转为灰度并进行模糊处理cvtColor( src, src_gray, COLOR_BGR2GRAY );blur( src_gray, src_gray, Size(3,3) );/// Create Window // 创建窗口const char* source_window = "Source";namedWindow( source_window );imshow( source_window, src );const int max_thresh = 255; // 定义阈值上限createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback ); // 创建滑动条thresh_callback( 0, 0 );waitKey(); // 等待用户按键退出return 0;
}/*** @function thresh_callback // 阈值回调函数*/
void thresh_callback(int, void* )
{/// Detect edges using Canny // 使用Canny方法进行边缘检测Mat canny_output;Canny( src_gray, canny_output, thresh, thresh*2 );/// Find contours // 寻找轮廓vector<vector<Point> > contours;findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );/// Find the convex hull object for each contour // 对每个轮廓寻找凸包物体vector<vector<Point> >hull( contours.size() );for( size_t i = 0; i < contours.size(); i++ ){convexHull( contours[i], hull[i] );}/// Draw contours + hull results // 将轮廓和凸包结果绘制出来Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );for( size_t i = 0; i< contours.size(); i++ ){Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );drawContours( drawing, contours, (int)i, color );drawContours( drawing, hull, (int)i, color );}/// Show in a window // 在窗口中显示结果imshow( "Hull demo", drawing );
}
上述代码是一个使用OpenCV进行图像轮廓检测的示例。主函数中先将图像从彩色图转化为灰度图,并进行了模糊处理,然后通过Canny边缘检测器寻找图像的边缘,定义阈值滑动条来动态改变Canny检测的阈值。接着通过findContours函数找到所有的轮廓,convexHull函数找到每个轮廓的凸包物体,最后将所有的轮廓和凸包物体绘制在一个全黑的图像上,颜色随机生成,然后在窗口中展示出来。
5. moments_demo.cpp计算图像中的轮廓的矩(包括面积、重心等)并进行显示
此源文件是用来演示如何使用OpenCV库进行图像轮廓分析的。其中定义了两个函数:main
和thresh_callback
。
main
函数是程序的入口函数。尝试从命令行参数中读取输入的图像文件(如果没有给出图像,则默认读取stuff.jpg
),然后将图像转化为灰度图,最后对其进行模糊处理。创建一个窗口显示原始图像,并创建一个滑动条来调整Canny算子阈值。然后调用thresh_callback
函数对图像进行处理,并等待用户关闭窗口。thresh_callback
函数负责接受Canny算子阈值,并使用该值对灰度图像进行边缘检测。然后,它找到检测到的边缘的轮廓,并计算出这些轮廓的几何中心。最后,它在一个新的图像上绘制出这些轮廓,并在每个轮廓的几何中心处画一个圆点。画出的图像会在一个新窗口中显示出来。然后,此函数将根据计算出来的几何中心,对于每一个轮廓,打印其面积(即轮廓内部的像素点数)以及轮廓的长度(即轮廓上的像素点数)。
/*** @function moments_demo.cpp* @brief 演示如何计算图像的矩* @author OpenCV团队*/#include "opencv2/imgcodecs.hpp" // 引入OpenCV中用于图像编码解码的函数库
#include "opencv2/highgui.hpp" // 引入OpenCV中用于创建GUI界面的函数库
#include "opencv2/imgproc.hpp" // 引入OpenCV的图像处理库
#include <iostream> // 引入C++标准库中提供的函数对象来进行输入/输出的库
#include <iomanip> // using namespace cv; // 使用OpenCV中的所有函数和类
using namespace std; // 使用C++标准库中的所有函数和类Mat src_gray; // 定义存储灰度图的Mat类型变量
int thresh = 100; // 定义阈值
RNG rng(12345); // 定义随机数生成器/// 函数声明
void thresh_callback(int, void* );/*** @function main* 主函数*/
int main( int argc, char** argv )
{/// 加载源图片CommandLineParser parser( argc, argv, "{@input | stuff.jpg | input image}" );// 读取图片Mat src = imread( samples::findFile( parser.get<String>( "@input" ) ) );if( src.empty() ) // 如果图片为空{cout << "Could not open or find the image!\n" << endl; // 打印错误信息cout << "usage: " << argv[0] << " <Input image>" << endl; // 打印使用说明return -1; // 返回-1退出}/// 将图片转换为灰度图并进行模糊处理cvtColor( src, src_gray, COLOR_BGR2GRAY ); // 转为灰度图blur( src_gray, src_gray, Size(3,3) ); // 进行模糊处理/// 创建窗口const char* source_window = "Source"; // 定义窗口名称namedWindow( source_window ); // 创建窗口imshow( source_window, src ); // 在窗口中显示图像const int max_thresh = 255; // 定义最大阈值// 创建阈值滑动条,并绑定thresh_callback函数createTrackbar( "Canny thresh:", source_window, &thresh, max_thresh, thresh_callback );// 调用thresh_callback函数thresh_callback( 0, 0 );// 等待用户动作waitKey();return 0;
}/*** @function thresh_callback* 阈值回调函数*/
void thresh_callback(int, void* )
{/// 使用Canny算子检测边缘Mat canny_output; // 声明一个Mat对象用来存储Canny检测的结果Canny( src_gray, canny_output, thresh, thresh*2, 3 ); // 执行Canny边缘检测/// 寻找轮廓vector<vector<Point> > contours; // 定义容器存储寻找到的轮廓// 使用findContours函数在二值图像中寻找轮廓findContours( canny_output, contours, RETR_TREE, CHAIN_APPROX_SIMPLE );/// 计算矩vector<Moments> mu(contours.size() ); // 定义一个容器存储所有轮廓的矩for( size_t i = 0; i < contours.size(); i++ ) // 遍历所有的轮廓{mu[i] = moments( contours[i] ); // 计算每一个轮廓的矩}/// 获取质心vector<Point2f> mc( contours.size() ); // 申明一个容器存储每一个轮廓的质心for( size_t i = 0; i < contours.size(); i++ ) // 遍历所有轮廓{// 计算每个轮廓的质心,避免零除错误mc[i] = Point2f( static_cast<float>(mu[i].m10 / (mu[i].m00 + 1e-5)),static_cast<float>(mu[i].m01 / (mu[i].m00 + 1e-5)) );cout << "mc[" << i << "]=" << mc[i] << endl; // 输出计算结果}/// 画出轮廓Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 ); // 创建一个用于绘制轮廓的黑色画布for( size_t i = 0; i< contours.size(); i++ ) // 遍历所有轮廓{// 随机生成颜色值Scalar color = Scalar( rng.uniform(0, 256), rng.uniform(0,256), rng.uniform(0,256) );drawContours( drawing, contours, (int)i, color, 2 ); // 将轮廓画到画布上circle( drawing, mc[i], 4, color, -1 ); // 将质心画到画布上}/// 在窗口中显示结果imshow( "Contours", drawing );/// 使用矩的00计算面积,并与OpenCV函数的结果比较cout << "\t Info: Area and Contour Length \n";for( size_t i = 0; i < contours.size(); i++ ) // 遍历所有轮廓{cout << " * Contour[" << i << "] - Area (M_00) = " << std::fixed << std::setprecision(2) << mu[i].m00<< " - Area OpenCV: " << contourArea(contours[i]) << " - Length: " << arcLength( contours[i], true ) << endl;}
}
这段代码是使用OpenCV的C++接口进行图像处理的示例程序,它主要的功能是计算图像中的轮廓的矩(包括面积、重心等)并进行显示。具体步骤包括:读入图像、转成灰度图、进行模糊处理、使用Canny算法进行边缘检测、寻找和绘制轮廓、计算轮廓的矩并获取质心、比较矩计算的面积和OpenCV函数计算的面积。
终端输出:
mc[0]=[328.222, 331.944]
mc[1]=[334.476, 323.523]
mc[2]=[213.035, 312.397]
mc[3]=[194.211, 171.352]
mc[4]=[75.8505, 101.182]
mc[5]=[75.9116, 101.259]
mc[6]=[197.533, 57.6664]
mc[7]=[197.166, 64.3331]
mc[8]=[225.274, 57.9121]Info: Area and Contour Length* Contour[0] - Area (M_00) = 9.00 - Area OpenCV: 9.00 - Length: 148.08* Contour[1] - Area (M_00) = 7.00 - Area OpenCV: 7.00 - Length: 140.77* Contour[2] - Area (M_00) = 23.50 - Area OpenCV: 23.50 - Length: 176.75* Contour[3] - Area (M_00) = 269.00 - Area OpenCV: 269.00 - Length: 1217.62* Contour[4] - Area (M_00) = 233.00 - Area OpenCV: 233.00 - Length: 80.91* Contour[5] - Area (M_00) = 207.50 - Area OpenCV: 207.50 - Length: 72.67* Contour[6] - Area (M_00) = 2.50 - Area OpenCV: 2.50 - Length: 35.56* Contour[7] - Area (M_00) = 3.00 - Area OpenCV: 3.00 - Length: 38.97* Contour[8] - Area (M_00) = 64.50 - Area OpenCV: 64.50 - Length: 511.63
mc[0]=[328.22, 331.94]
mc[1]=[334.48, 323.52]
mc[2]=[213.04, 312.40]
mc[3]=[194.21, 171.35]
mc[4]=[75.85, 101.18]
mc[5]=[75.91, 101.26]
mc[6]=[197.53, 57.67]
mc[7]=[197.17, 64.33]
mc[8]=[225.27, 57.91]Info: Area and Contour Length* Contour[0] - Area (M_00) = 9.00 - Area OpenCV: 9.00 - Length: 148.08* Contour[1] - Area (M_00) = 7.00 - Area OpenCV: 7.00 - Length: 140.77* Contour[2] - Area (M_00) = 23.50 - Area OpenCV: 23.50 - Length: 176.75* Contour[3] - Area (M_00) = 269.00 - Area OpenCV: 269.00 - Length: 1217.62* Contour[4] - Area (M_00) = 233.00 - Area OpenCV: 233.00 - Length: 80.91* Contour[5] - Area (M_00) = 207.50 - Area OpenCV: 207.50 - Length: 72.67* Contour[6] - Area (M_00) = 2.50 - Area OpenCV: 2.50 - Length: 35.56* Contour[7] - Area (M_00) = 3.00 - Area OpenCV: 3.00 - Length: 38.97* Contour[8] - Area (M_00) = 64.50 - Area OpenCV: 64.50 - Length: 511.63
mc[0]=[328.22, 331.94]
mc[1]=[334.48, 323.52]
mc[2]=[213.04, 312.40]
mc[3]=[194.21, 171.35]
mc[4]=[75.85, 101.18]
mc[5]=[75.91, 101.26]
mc[6]=[197.53, 57.67]
mc[7]=[197.17, 64.33]
mc[8]=[225.27, 57.91]Info: Area and Contour Length* Contour[0] - Area (M_00) = 9.00 - Area OpenCV: 9.00 - Length: 148.08* Contour[1] - Area (M_00) = 7.00 - Area OpenCV: 7.00 - Length: 140.77* Contour[2] - Area (M_00) = 23.50 - Area OpenCV: 23.50 - Length: 176.75* Contour[3] - Area (M_00) = 269.00 - Area OpenCV: 269.00 - Length: 1217.62* Contour[4] - Area (M_00) = 233.00 - Area OpenCV: 233.00 - Length: 80.91* Contour[5] - Area (M_00) = 207.50 - Area OpenCV: 207.50 - Length: 72.67* Contour[6] - Area (M_00) = 2.50 - Area OpenCV: 2.50 - Length: 35.56* Contour[7] - Area (M_00) = 3.00 - Area OpenCV: 3.00 - Length: 38.97* Contour[8] - Area (M_00) = 64.50 - Area OpenCV: 64.50 - Length: 511.63
mc[0]=[328.22, 331.94]
mc[1]=[334.48, 323.52]
mc[2]=[213.04, 312.40]
mc[3]=[194.21, 171.35]
mc[4]=[75.85, 101.18]
mc[5]=[75.91, 101.26]
mc[6]=[197.53, 57.67]
mc[7]=[197.17, 64.33]
mc[8]=[225.27, 57.91]Info: Area and Contour Length* Contour[0] - Area (M_00) = 9.00 - Area OpenCV: 9.00 - Length: 148.08* Contour[1] - Area (M_00) = 7.00 - Area OpenCV: 7.00 - Length: 140.77* Contour[2] - Area (M_00) = 23.50 - Area OpenCV: 23.50 - Length: 176.75* Contour[3] - Area (M_00) = 269.00 - Area OpenCV: 269.00 - Length: 1217.62* Contour[4] - Area (M_00) = 233.00 - Area OpenCV: 233.00 - Length: 80.91* Contour[5] - Area (M_00) = 207.50 - Area OpenCV: 207.50 - Length: 72.67* Contour[6] - Area (M_00) = 2.50 - Area OpenCV: 2.50 - Length: 35.56* Contour[7] - Area (M_00) = 3.00 - Area OpenCV: 3.00 - Length: 38.97* Contour[8] - Area (M_00) = 64.50 - Area OpenCV: 64.50 - Length: 511.63
mc[0]=[328.22, 331.94]
mc[1]=[334.48, 323.52]
mc[2]=[213.04, 312.40]
mc[3]=[194.21, 171.35]
mc[4]=[75.85, 101.18]
mc[5]=[75.91, 101.26]
mc[6]=[197.53, 57.67]
mc[7]=[197.17, 64.33]
mc[8]=[225.27, 57.91]Info: Area and Contour Length* Contour[0] - Area (M_00) = 9.00 - Area OpenCV: 9.00 - Length: 148.08* Contour[1] - Area (M_00) = 7.00 - Area OpenCV: 7.00 - Length: 140.77* Contour[2] - Area (M_00) = 23.50 - Area OpenCV: 23.50 - Length: 176.75* Contour[3] - Area (M_00) = 269.00 - Area OpenCV: 269.00 - Length: 1217.62* Contour[4] - Area (M_00) = 233.00 - Area OpenCV: 233.00 - Length: 80.91* Contour[5] - Area (M_00) = 207.50 - Area OpenCV: 207.50 - Length: 72.67* Contour[6] - Area (M_00) = 2.50 - Area OpenCV: 2.50 - Length: 35.56* Contour[7] - Area (M_00) = 3.00 - Area OpenCV: 3.00 - Length: 38.97* Contour[8] - Area (M_00) = 64.50 - Area OpenCV: 64.50 - Length: 511.63
mc[0]=[328.22, 331.94]
mc[1]=[334.48, 323.52]
mc[2]=[213.04, 312.40]
mc[3]=[194.21, 171.35]
mc[4]=[75.88, 101.20]
mc[5]=[75.91, 101.26]
mc[6]=[197.53, 57.67]
mc[7]=[197.17, 64.33]
mc[8]=[225.27, 57.91]Info: Area and Contour Length* Contour[0] - Area (M_00) = 9.00 - Area OpenCV: 9.00 - Length: 148.08* Contour[1] - Area (M_00) = 7.00 - Area OpenCV: 7.00 - Length: 140.77* Contour[2] - Area (M_00) = 23.50 - Area OpenCV: 23.50 - Length: 174.75* Contour[3] - Area (M_00) = 269.00 - Area OpenCV: 269.00 - Length: 1217.62* Contour[4] - Area (M_00) = 232.50 - Area OpenCV: 232.50 - Length: 79.50* Contour[5] - Area (M_00) = 207.50 - Area OpenCV: 207.50 - Length: 72.67* Contour[6] - Area (M_00) = 2.50 - Area OpenCV: 2.50 - Length: 35.56* Contour[7] - Area (M_00) = 3.00 - Area OpenCV: 3.00 - Length: 38.97* Contour[8] - Area (M_00) = 64.50 - Area OpenCV: 64.50 - Length: 511.63
6. pointPolygonTest_demo.cpp 创建和绘制一个多边形图像然后计算并显示图像上每个点到这个多边形的距离
这段代码是一个C++程序,使用了OpenCV库,主要实现了创建和绘制一个多边形图像然后计算并显示图像上每个点到这个多边形的距离。
主要步骤如下:
创建一个4r x 4r的全零矩阵作为图像(r=100,因此图像的大小为400x400;
定义一个六边形的顶点,并将几何图形画在图像上;
使用
findContours
方法从图像中提取轮廓;计算图像上每个点到轮廓的距离,并存储在一个单独的矩阵中;
查找离多边形最远和最近的点,获取最大和最小的距离值;
为距离图像上色,表示点到多边形的距离,其中蓝色表示该点在多边形内部,红色表示在外部,白色表示在边界上;
在距离最远的点处画一个圆,圆心为此点,半径为最大距离;
最后展示原始图像和距离图像。
典型的方法和数据结构包括:
Mat:是OpenCV库中的一个主要数据结构,用于存储图像和矩阵数据;
Point:OpenCV中的一个数据结构,储存2D点的坐标(x,y);
findContours:OpenCV的一个函数,用于在二值图像中查找轮廓;
pointPolygonTest:OpenCV中的一个函数,用于计算2D点到一个多边形的最短距离;
imshow:OpenCV的一个函数,用于显示图像;
waitKey:OpenCV的一个函数,用于等待用户按键,如果没有这行代码,imshow显示的图像窗口会立即消失;如果参数为0,表示窗口将持续显示,直到用户关闭它为止。
同时需要注意的是,这段代码只针对单通道黑白图像进行处理。如果要处理多通道图像,还需要进行相应的修改。
/*** @function pointPolygonTest_demo.cpp //定义了程序的入口函数main函数* @brief Demo用来距离检测函数示例——相当简单 //描述了这段代码的主要功能* @author OpenCV team //说明这段代码的作者*/// 导入opencv的用户选择界面(UI)库和图像处理库
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"// 导入C++标准输入输出库
#include <iostream> // 名字空间的定义,方便在代码中使用opencv和std库的函数和对象
using namespace cv;
using namespace std; /*** @function main //定义了程序的入口函数main函数*/
int main( void ) //定义了程序的入口函数main函数
{/// 创建一个图像// 初始化图像src的大小与类型 const int r = 100; //定义了一个常量r,用于确定绘制图形边长的依赖参数Mat src = Mat::zeros( Size( 4*r, 4*r ), CV_8U ); //使用opencv的Mat类创建一个4r*4r大小的8位无符号整型全黑色(所有像素值都为0)图像,作为绘制六边形的画布/// 创建一系列的坐标点来生成一个轮廓// 建立一个包含6个Point2f对象的vert数组,用于存储六边形的六个顶点坐标vector<Point2f> vert(6);// 为数组的每个元素赋值,确定各顶点的坐标vert[0] = Point( 3*r/2, static_cast<int>(1.34*r) ); vert[1] = Point( 1*r, 2*r );vert[2] = Point( 3*r/2, static_cast<int>(2.866*r) );vert[3] = Point( 5*r/2, static_cast<int>(2.866*r) );vert[4] = Point( 3*r, 2*r );vert[5] = Point( 5*r/2, static_cast<int>(1.34*r) );/// 在src上绘制图形// 对vert数组中的每个元素都执行循环操作,用line函数在src图像上绘制从第i个顶点到下一个顶点的线段,颜色为白色,线条粗细为3。总的效果就是在src上绘制了一个白色边框的六边形for( int i = 0; i < 6; i++ ){line( src, vert[i], vert[(i+1)%6], Scalar( 255 ), 3 );}/// 获取轮廓// 建立一个contours二维数组,作为存储src中所有轮廓的容器vector<vector<Point> > contours;// 使用findContours方法在src图像中寻找轮廓,findContours会先使用阈值将图像二值化,然后寻找二值化图像中的轮廓。经过该操作后,contours中将包含src图像中所有轮廓的顶点坐标的列表findContours( src, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);/// 计算到轮廓的最短距离// 创建raw_dist图像,用于存储src中每个点到最近轮廓的最短距离Mat raw_dist( src.size(), CV_32F );// 对src中的每个像素都执行循环操作:for( int i = 0; i < src.rows; i++ ){for( int j = 0; j < src.cols; j++ ){// 使用pointPolygonTest方法计算src中点(j,i)到最近轮廓的最短距离,然后将计算结果存入raw_dist相应位置raw_dist.at<float>(i,j) = (float)pointPolygonTest( contours[0], Point2f((float)j, (float)i), true );}}// 创建minVal和maxVal两个变量,作为存储raw_dist中的最小值和最大值的容器double minVal, maxVal;// 创建maxDistPt对象,作为存储最大距离对应坐标的容器Point maxDistPt;// minMaxLoc方法会在raw_dist矩阵中寻找最小和最大值,然后分别赋值给minVal和maxVal。同时,minMaxLoc找到的最大值的坐标将赋值给maxDistPtminMaxLoc(raw_dist, &minVal, &maxVal, NULL, &maxDistPt);// minVal和maxVal都取绝对值minVal = abs(minVal);maxVal = abs(maxVal);// 创建drawing空白图像,用于后续的绘制操作Mat drawing = Mat::zeros( src.size(), CV_8UC3 );// 对于src图像中的每个像素,依次执行以下操作for( int i = 0; i < src.rows; i++ ){for( int j = 0; j < src.cols; j++ ){// 如果raw_dist中存储的距离值小于零,则在drawing中的对应位置绘制蓝色,蓝色程度按照距离值的绝对值的大小确定if( raw_dist.at<float>(i,j) < 0 ){drawing.at<Vec3b>(i,j)[0] = (uchar)(255 - abs(raw_dist.at<float>(i,j)) * 255 / minVal);}// 如果raw_dist中存储的距离值大于零,则在drawing中的对应位置绘制红色,红色程度按照距离值的大小确定else if( raw_dist.at<float>(i,j) > 0 ){drawing.at<Vec3b>(i,j)[2] = (uchar)(255 - raw_dist.at<float>(i,j) * 255 / maxVal);}// 如果raw_dist中存储的距离值等于零,则在drawing中的对应位置绘制白色else{drawing.at<Vec3b>(i,j)[0] = 255;drawing.at<Vec3b>(i,j)[1] = 255;drawing.at<Vec3b>(i,j)[2] = 255;}}}// 绘制一个以最大距离所在的点为圆心,最大距离为半径的白色圆形circle(drawing, maxDistPt, (int)maxVal, Scalar(255,255,255));/// 旋轉圖像imshow( "Source", src ); //显示原始图像imshow( "Distance and inscribed circle", drawing ); //显示带距离颜色及内切圆或者外接圆的图像// 一直等待,直到用户按下任意键waitKey();// 返回程序退出状态值return 0;
}
以上提供了代码,主要是在OpenCV中使用pointPolygonTest函数来计算点和多边形之间的最短距离,并且在图中绘制了点和多边形的关系。该代码中使用了C++和OpenCV库,是一个实际的图像处理过程,具有一定的实用价值,尤其是在图像处理、机器视觉等领域。点到线的距离往往是一个重要的参考因素,可以用于轮廓识别、影像匹配和匹配评分等任务。
相关文章:
【opencv】教程代码 —ShapeDescriptors
检测和显示图像的轮廓 在图像中搜索并显示轮廓边缘多边形、轮廓矩形和包围圆 获取包含检测到的轮廓的椭圆和旋转的矩形 图像轮廓检测和轮廓凸包 计算图像中的轮廓的矩(包括面积、重心等)并进行显示 创建和绘制一个多边形图像然后计算并显示图像上每个点到…...
2024-03-28 Java8之Collectors类
Collectors类常用方法 文章目录 Collectors类常用方法1.toList、toSet、toMap2.joining、counting、summingInt、minBy3.groupingBy 1.toList、toSet、toMap Collector<T, ?, List<T>> toList(); //收集为List集合 Collector<T, ?, Set<T>> toSet()…...
第116讲:使用Mycat-eye管理Mycat数据库服务
文章目录 1.Mycat的管理工具2.Mycat-eye介绍3.部署Mycat-eye3.1.安装Zookeep3.2.安装Mycat-eye3.3.访问Mycat-eye 4.在Mycat-eye中导入Mycat服务的信息 1.Mycat的管理工具 Mycat默认开通2个端口,可以在server.xml中进行修改。 8066 数据访问端口,即进行…...
XR虚拟直播间,引领创新风潮,打破直播局限!
随着互联网技术日新月异的发展,直播行业也迎来了蓬勃发展的春天。然而,大多数直播间在吸引观众眼球和延长用户观看时长方面,仍然面临着巨大的挑战。正是在这样的背景下,XR虚拟直播系统应运而生,以其多维度的直播场景、…...
unity双层滑动实现
实现功能: 当滑动列表中内容处于顶端的时候,向上滑动优先滑动整个滑动列表,当滑动列表移动到设置位置,即设定的最高处时,继续移动列表内内容。向下移动亦然,当内容处于滑动列表顶端时,移动整个滑…...
浅谈AI技术创业有哪些机会?
一、AI技术创业概念简介 AI技术创业指的是利用人工智能(Artificial Intelligence,AI)技术进行创业活动。人工智能是指计算机系统能够模拟和展现出人类智能的一种技术。在AI技术创业中,创业者利用AI技术来解决现实生活中的问题&…...
大数据-TXT文本重复行计数工具
支持系统类型:Windows 64位系统 Linux 64位系统 苹果64位系统 硬盘要求:固态硬盘(有效剩余磁盘空间大小最低3倍于大数据文件的大小) 内存要求:最低8G(例如只有几百G数据) 如果处理TB级大数据文…...
【无标题】331
2024年3月31日19:26:09 和一个好感度为40的女生完成了一次基础的对话 2024年3月31日19:26:26 在群里完成了一个毫无所谓的对话 2024年3月31日19:40:04开始准备写论文了 2024年3月31日19:40:11好感度为40的女生回复了我本质上是回复率只有40的人回复了我那应该感到高兴才对 …...
MIT最新研究成果 机器人能够从错误中纠偏 无需编程介入和重复演示
目前科学家们正在努力让机器人变得更加智能,教会他们完成诸如擦拭桌面,端盘子等复杂技能。以往机器人要在非结构化环境执行这样的任务,需要依靠固定编程进行,缺乏场景通用性,而现在机器人的学习过程主要在于模仿&#…...
C语言—指针数组
从键盘任意输入一个整型表示的月份值,用指针数组编程输出该月份的英文表示,若输入的月份值不在1~12之间,则输出“Illegal month”。 **输入格式要求:"%d" 提示信息:"Input month number:&q…...
OpenCV图像二值化
1.二值图像 灰度图像 0 - 255二值图像 0(黑) / 255(白) 2.二值分割 五种阈值分割方法(阈值T): 大于T为255,小于T为0 大于T为0,小于T为255 小于T为原值 else T 小于…...
java中的抽象类
抽象类是指包含了抽象方法的类。在java中,抽象方法指的是用abstract关键字进行修饰的方法,抽象方法与普通的方法的最大区别就是抽象方法没有方法体,也就是说抽象方法是没有具体的实现的。这也就意味着在抽象类的子类中调用抽象方法时…...
代码随想录算法训练营第二十天| 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
系列文章目录 目录 系列文章目录654.最大二叉树递归法[左闭右开)[左闭右闭] 617.合并二叉树递归法(前中后序都可,以前序为例)迭代法(类似 101. 对称二叉树 写法,可用双端队列/单端队列<栈>,以单端队列…...
2014年认证杯SPSSPRO杯数学建模A题(第二阶段)轮胎的花纹全过程文档及程序
2014年认证杯SPSSPRO杯数学建模 A题 轮胎的花纹 原题再现: 轮胎被广泛使用在多种陆地交通工具上。根据性能的需要,轮胎表面常会加工出不同形状的花纹。在设计轮胎时,往往要针对其使用环境,设计出相应的花纹形状。 第二阶段问…...
C#全新一代医院手术麻醉系统围术期全流程源码
目录 一、麻醉学科的起源 二、麻醉前访视与评估记录单 患者基本信息 临床诊断 患者重要器官功能及疾病情况 病人体格情况分级 手术麻醉风险评估 拟施麻醉方法及辅助措施 其他需要说明的情况 访视麻醉医师签名 访视时间 与麻醉相关的检查结果 三、手术麻醉信息系统…...
Python 神器:一键下载 M3U8 并转换为 MP4
在这个数字时代,我们经常在网页上遇到各种精彩的视频,但往往只能观看而无法下载。今天,我将向大家介绍如何使用 Python 自动下载网页中的 M3U8 链接,并将其转换为 MP4 格式,让你轻松保存喜欢的视频! 一、准…...
vue3全局控制Element plus所有组件的文字大小
项目框架vue-右上角有控制全文的文字大小 实现: 只能控制element组件的文字及输入框等大小变化,如果是自行添加div,text, span之类的控制不了。 配置流程 APP.vue 使用element的provide,包含app <el-config-provider :locale"loca…...
区间预测 | Matlab实现带有置信区间的BP神经网络时间序列未来趋势预测
区间预测 | Matlab实现带有置信区间的BP神经网络时间序列未来趋势预测 目录 区间预测 | Matlab实现带有置信区间的BP神经网络时间序列未来趋势预测预测效果基本介绍研究回顾程序设计参考资料预测效果 基本介绍 BP神经网络(Backpropagation neural network)是一种常用的人工神…...
Matlab中的脚本和函数
Matlab中的脚本和函数 文章目录 Matlab中的脚本和函数脚本创建脚本代码注释函数创建函数局部函数嵌套函数私有函数匿名函数补充知识函数句柄测试环境:Win11 + Matlab R2021a 脚本 Matlab脚本是最简单的程序文件类型。它们可用于自动执行一系列 Matlab 命令,如命令行重复执…...
使用 nohup java - jar 不输出nohup日志
使用 nohup 命令来运行 Java 程序,并且不让输出写入 nohup.out 文件,可以使用重定向操作符 > 将标准输出重定向到 /dev/null 文件中。这样可以将输出丢弃,而不会写入日志文件。下面是具体的命令: nohup java -jar your_progra…...
Linux系统中安装一些常用的插件备用
Linux系统中安装一些常用的插件备用 1.安装wget yum -y install wget 2.安装vim yum -y install vim-enhanced 3.更换yum源为国内的阿里云源(选择) 1、备份CentOS-Base.repo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.…...
笔记本电脑上部署LLaMA-2中文模型
尝试在macbook上部署LLaMA-2的中文模型的详细过程。 (1)环境准备 MacBook Pro(M2 Max/32G); VMware Fusion Player 版本 13.5.1 (23298085); Ubuntu 22.04.2 LTS; 给linux虚拟机分配8*core CPU 16G RAM。 我这里用的是16bit的量化模型,…...
百度云加速方法「Cheat Engine」
加速网盘下载 相信经常玩游戏的小伙伴都知道「Cheat Engine」这款游戏内存修改器,它除了能对游戏进行内存扫描、调试、反汇编 之外,还能像变速齿轮那样进行本地加速。 这款专注游戏的修改器,被大神发现竟然还能加速百度网盘资源下载…...
SOC内部集成网络MAC外设+ PHY网络芯片方案:PHY芯片基础知识
一. 简介 本文简单了解一下 "SOC内部集成网络MAC外设 PHY网络芯片方案" 这个网络硬件方案中涉及的 PHY网络芯片的基础知识。 二. PHY芯片基础知识 PHY 是 IEEE 802.3 规定的一个标准模块。 1. IEEE规定了PHY芯片的前 16个寄存器功能是一样的 前面说了…...
openGauss 6.0.0-RC1 版本正式发布!
openGauss 6.0.0-RC1版本正式上线! openGauss 6.0.0-RC1是社区最新发布的创新版本,版本生命周期为0.5年。(创新版本命名:由原方案 XX.1.0 Preview (例:5.1.0 preview),调整为现方案 XX.0.0-RCx&…...
【JVM】关于JVM垃圾回收
文章目录 🌴死亡对象的判断算法🌸引用计数算法🌸可达性分析算法 🌳垃圾回收算法🌸标记-清除算法🌸复制算法🌸标记-整理算法🌸分代算法🌸哪些对象会进入新生代?…...
Unity照片墙简易圆形交互效果总结
还要很多可以优化的点地方,有兴趣的可以做 比如对象的销毁和生成可以做成对象池,走到最左边后再移动到最右边循环利用 分析过程文件,采用Blender,资源已上传,可以播放动画看效果,下面截个图: …...
Unity2018发布安卓报错 Exception: Gradle install not valid
Unity2018发布安卓报错 Exception: Gradle install not valid Exception: Gradle install not valid UnityEditor.Android.GradleWrapper.Run (System.String workingdir, System.String task, System.Action1[T] progress) (at <c67d1645d7ce4b76823a39080b82c1d1>:0) …...
蓝桥杯省赛刷题——题目 2656:刷题统计
刷题统计OJ链接:蓝桥杯2022年第十三届省赛真题-刷题统计 - C语言网 (dotcpp.com) 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a 道题目,周六和周日每天做 b 道题目。请你帮小明计算,按照计划他将在第几…...
Python爬虫之异步爬虫
异步爬虫 一、协程的基本原理 1、案例 案例网站:https://www.httpbin.org/delay/5、这个服务器强制等待了5秒时间才返回响应 测试:用requests写一个遍历程序,遍历100次案例网站: import requests import logging import time…...
优秀网站欣赏/如何免费制作网站
三层架构(3-tier architecture) 1、用户界面层(User Interface layer)2、业务逻辑层(Business Logic Layer)3、数据访问层(Data access layer)思想:高内聚低耦合面向接口设计的思想“抽屉”式架…...
深圳市住建局和建设局官网/seo排名怎么做
参考链接: class.__mro__ 参考链接: class.mro() 参考链接: class.__subclasses__() 实验代码展示: # class Person(): # class Person(object): # class Person: class Person: # class Person(object): # class Person: # class Person(): 这三种写法都是可以的定义基类Pe…...
塘下春华网站建设/站长工具百科
Backdrill相关设置及Backdrill文档输出方法...
themebox wordpress/怎么免费注册域名
文章来源教师范文吧大班数学:数字接龙活动目标:1.引发幼儿对一组数字的记忆与敏感性,培养孩子的专注力。2.理解并遵守规则,按不同任务要求进行游戏。活动准备:任务卡,游戏币活动过程:一、颠三倒…...
wordpress改图片地址/seo网站优化方
ILI9341-TFT LCD驱动(基于TFT_eSPI库) 液晶显示器 (LCD) 是一种平板显示器或其他电子调制光学设备,它利用液晶与偏振器的光调制特性。液晶不直接发光,而是使用背光或反射器来产生彩色或单色图像。LCD 可用于显示任意图像(如在通用计算机显示器中)或具有低信息内容的固定…...
西安做网站哪家公司好/深圳新闻今日最新
1.个人隐私问题 个人隐私包括传统的个人隐私和现代个人数据。传统的个人隐私有姓名,出生年月,身份证编号,婚姻家庭,教育等。现代个人数据有用户名和密码,IP地址等。合理合法的隐私应受到保护。在计算机时代,…...