opencv学习二值分析

内容来源于《opencv4应用开发入门、进阶与工程化实践》 

二值分析:

常见的二值化方法:

  • 基于全局阈值(threshold)得到的二值图像;
  • 基于自适应阈值(adaptiveThreshold)得到的二值图像;
  • 边缘检测(Canny)
  • 基于像素值范围(inRange)

threshold 

thresholdType介绍:

  • THRESH_BINARY表示大于thresh的取maxval,否则取0;
  • THRESH_BINARY_INV表示大于thresh的取0,否则取maxvalue;
  • THRESH_TRUNC表示大于threshthreshold,否则不改变灰度值;
  • THRESH_TOZERO表示大于thresh的不改变灰度值,否则取0;
  • THRESH_TOZERO_INV表示大于thresh取0,窦泽不改变灰度值;
  • THRESH_OTSU表示使用otsu自动计算阈值;
  • THRESH_TRIANGLE表示使用Triangle自动计算阈值;

adaptiveThreshold

void adaptiveThreshold( InputArray src, OutputArray dst,double maxValue, int adaptiveMethod,int thresholdType, int blockSize, double C );
  • src表示需要进行二值化的图像;需要注意的是,该输入必须是8-bit单通道的图像;
  • dst表示输出图像的二值图像;
  • maxValue是一个非零值,用于对哪些满足条件的阈值进行赋值;
  • adaptiveMethod表示选择哪一种自适应阈值算法;Opencv提供两种,ADAPTIVE_THRESH_MEAN_CADAPTIVE_THRESH_GAUSSIAN_C,下面会详细介绍;
  • thresholdType表示二值化类型,OpenCV提供两种, THRESH_BINARYTHRESH_BINARY_INV,下面会详细介绍;
  • blocksize表示参与计算的像素的领域范围,必须使用奇数;
  • C可以为正数, 零或者负数;用于在计算过程中容忍程度;
thresholdType介绍

adaptiveMethod介绍

第一种ADAPTIVE_THRESH_MEAN_C,针对像素(x,y)的计算方式如下:

  • T(x,y)结果是在(x,y)的邻域blockSize×blockSize范围内所有灰度值的均值减去C�;

第二种ADAPTIVE_THRESH_GAUSSIAN_C,针对像素(x,y)的计算方式如下:

  • 首先,生成一个大小为blockSize×blockSize的高斯核,作为权重;
  • 其次,利用高斯核与(x,y)邻域范围内灰度值,进行加权求和,再减去C,得到T(x,y);

高斯核:符合高斯分布,距离越近权重越大。 

Canny

标准的边缘检测算法包括如下几步:

  1. 将图像转为灰度图像
  2. 通过高斯模糊卷积实现降噪
  3. 计算图像梯度的大小与角度
  4. 非最大信号压制
  5. 双阈值边缘连接

在图像利用Sobel算子(也是滤波函数)计算x, y两个方向的梯度: 

 其次,计算梯度的强度和方向:(根据X轴和Y轴方向的梯度可以计算图像中像素点的梯度幅值G与角度θ)

非最大抑制 

理想情况下只有边缘像素的梯度是大于阈值T的,但实际情况下,局部也会出现多个高梯度阈值,所以要需要每个像素根据自身角度方向与两侧像素梯度值进行比较,如果当前像素点的梯度值小于两侧像素的梯度值,则将当前像素点的值设置为0;如果大于两侧像素的梯度值则保留。

双阈值连接

双阈值连接时保证边缘连续的关键步骤。一个高阈值H,一个低阈值L。

双阈值连接首先使用L对梯度图像进行处理,高于L保留,低于L丢弃,并将值设为零。然后使用H进行处理,高于H都视为边缘像素点。梯度值在[L,H]之间的:如果从低阈值像素点出发,最终可以通过相邻的像素点连接到高阈值像素点,而且整个连线上的像素点梯度值都大于L,则保留;否则设置为0。

轮廓发现与轮廓绘制

轮廓发现:

void findContours//提取轮廓,用于提取图像的轮廓
(
InputOutputArray image,//输入图像,必须是8位单通道图像,并且应该转化成二值的
OutputArrayOfArrays contours,//检测到的轮廓,每个轮廓被表示成一个point向量
OutputArray hierarchy,//可选的输出向量,包含图像的拓扑信息。其中元素的个数和检测到的轮廓的数量相等
int mode,//说明需要的轮廓类型和希望的返回值方式
int method,//轮廓近似方法
Point offset = Point()
)

轮廓绘制:

void drawContours//绘制轮廓,用于绘制找到的图像轮廓
(InputOutputArray image,//要绘制轮廓的图像InputArrayOfArrays contours,//所有输入的轮廓,每个轮廓被保存成一个point向量int contourIdx,//指定要绘制轮廓的编号,如果是负数,则绘制所有的轮廓const Scalar& color,//绘制轮廓所用的颜色int thickness = 1, //绘制轮廓的线的粗细,如果是负数,则轮廓内部被填充int lineType = 8, /绘制轮廓的线的连通性InputArray hierarchy = noArray(),//关于层级的可选参数,只有绘制部分轮廓时才会用到int maxLevel = INT_MAX,//绘制轮廓的最高级别,这个参数只有hierarchy有效的时候才有效//maxLevel=0,绘制与输入轮廓属于同一等级的所有轮廓即输入轮廓和与其相邻的轮廓//maxLevel=1, 绘制与输入轮廓同一等级的所有轮廓与其子节点。//maxLevel=2,绘制与输入轮廓同一等级的所有轮廓与其子节点以及子节点的子节点Point offset = Point()
)

代码示例:

void BinaryAnalysis::find_contours_demo(Mat &image) {Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);std::vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(gray, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());Mat result = Mat::zeros(image.size(), image.type());drawContours(result, contours, -1, Scalar(0, 0, 255), 2, 8);imshow("轮廓发现", result);
}

轮廓测量

轮廓测量指对二值图像的每个轮廓的弧长和面积进行测量,根据轮廓的面积和弧长对大小不同的对象实现查找、过滤与处理的操作,以寻找感兴趣的RoI区域。

计算面积:

//计算面积
double cv::contourArea(InputArray contourbool oriented = false
)
//计算弧长、周长
double cv::arcLength(InputArray curvebool closed)
//计算轮廓外接矩形
Rect cv::boundingRect(InputArray array
)
//示例代码
void BinaryAnalysis::contours_analysis_demo(Mat &image) {// 二值化Mat gray, binary;cvtColor(image, gray, COLOR_BGR2GRAY);double t = threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);// 轮廓发现std::vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());Mat result = Mat::zeros(image.size(), image.type());drawContours(result, contours, -1, Scalar(0, 0, 255), 2, 8);// 轮廓测量for (size_t t = 0; t < contours.size(); t++) {Rect box = boundingRect(contours[t]);double area = contourArea(contours[t]);double arc = arcLength(contours[t], true);putText(result, format("area:%.2f", area), box.tl(), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1, 8);putText(result, format("arc:%.2f", arc), Point(box.x, box.y+14), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 1, 8);}imshow("轮廓测量", result);
}

轮廓拟合逼近

//拟合椭圆
RotatedRect cv::fitEllipse(InputArray
)
//拟合直线
void cv::fitLine(InputArray pointsOutputArray lineint distType,double param,double reps,double aeps
)//distType表示拟合时使用的距离计算公式、、param表示对模型进行拟合距离计算的公式是否需要用到该参数。当distType参数为5,6,7时表示需要用到该参数,否则该参数不参与拟合距离计算、、reps与aeps表示对拟合结果的精度要求
//轮廓逼近
void cv::approxPolyDP(InputArray curveOutputArray approxCurvedouble epsilonbool closed
)

轮廓椭圆拟合与直线拟合示例代码:

//示例代码
void BinaryAnalysis::contours_fitness_demo(Mat &image) {// 二值化Mat edges;int t = 80;Canny(image, edges, t, t * 2, 3, false);//返回一个结构元素(卷积核),主要用于后续的膨胀腐蚀操作Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//膨胀函数对于3*3的核,取最大的数放在中心位置dilate(edges, edges, k);// 轮廓发现std::vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(edges, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());for (size_t t = 0; t < contours.size(); t++) {if (contours[t].size() < 5) {continue;}// 拟合椭圆// RotatedRect rrt = fitEllipse(contours[t]);// ellipse(image, rrt, Scalar(0, 0, 255), 2, 8);// 拟合直线Vec4f oneline;fitLine(contours[t], oneline, DIST_L1, 0, 0.01, 0.01);float vx = oneline[0];float vy = oneline[1];float x0 = oneline[2];float y0 = oneline[3];// 直线参数斜率k与截矩bfloat k = vy / vx;float b = y0 - k*x0;// 寻找轮廓极值点int minx = 0, miny = 10000;int maxx = 0, maxy = 0;for (int i = 0; i < contours[t].size(); i++) {Point pt = contours[t][i];if (miny > pt.y) {miny = pt.y;}if (maxy < pt.y) {maxy = pt.y;}}maxx = (maxy - b) / k;minx = (miny - b) / k;line(image, Point(maxx, maxy), Point(minx, miny), Scalar(0, 0, 255), 2, 8, 0);}imshow("轮廓拟合-直线拟合", image);
}

轮廓逼近示例代码:

void BinaryAnalysis::contours_apprv_demo(Mat &image) {Mat gray, binary;cvtColor(image, gray, COLOR_BGR2GRAY);double t = threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);std::vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(binary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());for (size_t t = 0; t < contours.size(); t++) {std::vector<Point> pts;approxPolyDP(contours[t], pts, 10, true);for (int i = 0; i < pts.size(); i++) {circle(image, pts[i], 3, Scalar(0, 0, 255), 2, 8, 0);}}imshow("轮廓逼近", image);
}

轮廓分析

可以根据轮廓发现得到的每个对象轮廓的最大外接矩形活最小外接矩形计算其横纵比,周长,面积。

下面的示例代码使用了轮廓测量与分析的相关函数,完成了对每个对象轮廓的分析,得到了每个对象轮廓的属性输出。

void BinaryAnalysis::contours_attrs_demo(Mat &image) {// 二值化Mat edges;int t = 80;Canny(image, edges, t, t * 2, 3, false);Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));dilate(edges, edges, k);// 轮廓发现std::vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(edges, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());Mat result = Mat::zeros(image.size(), image.type());drawContours(result, contours, -1, Scalar(0, 0, 255), 2, 8);imshow("轮廓发现", result);Mat mask = Mat::zeros(image.size(), CV_8UC1);for (size_t t = 0; t < contours.size(); t++) {Rect box = boundingRect(contours[t]);RotatedRect rrt = minAreaRect(contours[t]);std::vector<Point> hulls;convexHull(contours[t], hulls);double hull_area = contourArea(hulls);double box_area = box.width*box.height;double area = contourArea(contours[t]);// 计算横纵比double aspect_ratio = saturate_cast<double>(rrt.size.width) / saturate_cast<double>(rrt.size.height);// 计算延展度double extent = area / box_area;// 计算实密度double solidity = area / hull_area;// 生成mask与计算像素均值mask.setTo(Scalar(0));drawContours(mask, contours, t, Scalar(255), -1);Scalar bgra = mean(image, mask);putText(image, format("extent:%.2f", extent), box.tl(), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 1, 8);putText(image, format("solidity:%.2f", solidity), Point(box.x, box.y + 14), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 1, 8);putText(image, format("aspect_ratio:%.2f", aspect_ratio), Point(box.x, box.y + 28), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 1, 8);putText(image, format("mean:(%d,%d,%d)", (int)bgra[0], (int)bgra[1], (int)bgra[2]), Point(box.x, box.y + 42), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 0, 255), 1, 8);}imshow("轮廓分析", image);
}

直线检测圆检测

在二值图像分析中,直线检测和轮廓发现是经常遇到的处理要求。Opencv中的直线检测是基于霍夫变换完成的。

//标准霍夫直线检测
void cv::HoughLines(InputArray imageOutputArray linesdouble rho    //距离步长d=1,指该直线到原点的距离,对于屏幕坐标,原点是左上角的点double theta    //角度步长int threshold    //double srn =0double stn=0double min_theta=0double max_theta=CV_PI
)
//概率霍夫直线检测
void cv::HoughLinesP(InputArray imageOutputArray linesdouble rhodouble thetaint thresholddouble minLineLength=0double maxLineGap=0   
)
//霍夫圆检测
void cv::HoughCircle(InputArray imageOutputArray circles//输出圆心与直径int method     //方法,当前只支持基于梯度的方法double dp    //关键参数,累加分辨率double minDist //两个圆之间的最小距离double param1=100 //边缘检测中的高梯度阈值double param2=100 //边缘检测中的低梯度阈值int minRadius=0 //最小圆半径int maxRadius=0 //最大圆半径
)

示例代码:

void BinaryAnalysis::hough_line_demo(Mat &image) {Mat edges;Canny(image, edges, 50, 200, 3);vector<Vec2f> lines;HoughLines(edges, lines, 1, CV_PI / 180, 150, 0, 0);Mat result1, result2;cvtColor(edges, result1, COLOR_GRAY2BGR);result2 = result1.clone();for (size_t i = 0; i < lines.size(); i++){float rho = lines[i][0], theta = lines[i][1];Point pt1, pt2;double a = cos(theta), b = sin(theta);double x0 = a*rho, y0 = b*rho;pt1.x = cvRound(x0 + 1000 * (-b));pt1.y = cvRound(y0 + 1000 * (a));pt2.x = cvRound(x0 - 1000 * (-b));pt2.y = cvRound(y0 - 1000 * (a));line(result1, pt1, pt2, Scalar(0, 0, 255), 3, LINE_AA);}imshow("标准霍夫直线检测", result1);// 概率霍夫直线检测vector<Vec4i> linesP;HoughLinesP(edges, linesP, 1, CV_PI / 180, 50, 50, 10);for (size_t t = 0; t < linesP.size(); t++) {Point p1 = Point(linesP[t][0], linesP[t][1]);Point p2 = Point(linesP[t][2], linesP[t][3]);line(result2, p1, p2, Scalar(0, 0, 255), 2, 8, 0);}imshow("概率霍夫直线检测", result2);
}void BinaryAnalysis::hough_circle_demo(Mat &image) {Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);GaussianBlur(gray, gray, Size(5, 5), 0, 0);std::vector<Vec3f> circles;HoughCircles(gray, circles, HOUGH_GRADIENT_ALT, 2, 10, 100, 50, 20, 40);for (size_t t = 0; t < circles.size(); t++) {Vec3f c = circles[t];Point center = Point(c[0], c[1]);int radius = c[2];circle(image, center, radius, Scalar(255, 0, 255), 2, 8, 0); circle(image, center, 3, Scalar(255, 0, 0), 3, 8, 0);}imshow("霍夫圆检测", image);
}

最大内接圆与最小外接圆

opencv未提供API函数来寻找最大内接圆,但是可以通过点多边形测试函数巧妙地获取轮廓最大内接圆地半径,从而找到最大内接圆。

//最小外接圆
void cv::minEnclosingCircle(InputArray poointsPoint2f & centerfloat & radius
)
//点多边形测试函数
double cv::pointPolygonTest(InputArray contourPoint2f ptbool measureDist //是否测量距离,当measureDist设置为true时,返回的是该点到轮廓的真是距离。设置为false时,返回的是+1、0、-1
)
//示例代码
void BinaryAnalysis::inner_extenerl_circle_demo(Mat &image) {Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);std::vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(gray, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());for (size_t t = 0; t < contours.size(); t++) {// 最小外接圆Point2f pt;float radius;minEnclosingCircle(contours[t], pt, radius);circle(image, pt, radius, Scalar(255, 0, 0), 2, 8, 0);// 点多边形测试Mat raw_dist(image.size(), CV_32F);for (int i = 0; i < image.rows; i++){for (int j = 0; j < image.cols; j++){raw_dist.at<float>(i, j) = (float)pointPolygonTest(contours[t], Point2f((float)j, (float)i), true);}}// 获取最大内接圆半径double minVal, maxVal;Point maxDistPt; // inscribed circle centerminMaxLoc(raw_dist, &minVal, &maxVal, NULL, &maxDistPt);minVal = abs(minVal);maxVal = abs(maxVal);circle(image, maxDistPt, maxVal, Scalar(0, 0, 255), 2, 8, 0);}imshow("最大内接圆与最小外接圆演示", image);
}

轮廓匹配

二值图像轮廓发现可以得到每个圆形的轮廓,然后计算轮廓几何矩,再根据几何矩计算图像的中心位置。根据中心位置计算中心距,然后根据中心距计算中心归一化距。再根据归一化距计算胡距,最后比较轮廓胡距之间的相似性,从而实现轮廓匹配。

//几何矩、中心距、中心归一化距可通过moments函数一次就计算出来
Moments cv::moments(InoutArray arraybool binaryImage=false //是否为二值图像
)void cv::HuMoments(const Moments & momentsdouble hu[7] //胡距的7个值
)
//将胡距作为输入,对轮廓进行匹配。胡距具有缩放不变性与旋转不变性,所以进行轮廓外形匹配时,可以匹配到旋转与分辨率不一样的同一个轮廓。
//轮廓匹配函数
double cv::matchShapes(InputArray contour1InputArray contour2int method //比较方法double parameter //opencv3.x以后不需要
)
//示例代码
void BinaryAnalysis::contour_match_demo(Mat &image) {Mat src = imread("D:/images/abc.png");imshow("input", src);Mat src2 = imread("D:/images/a5.png");namedWindow("input2", WINDOW_FREERATIO);imshow("input2", src2);// 轮廓提取vector<vector<Point>> contours1;vector<vector<Point>> contours2;contours_info(src, contours1);contours_info(src2, contours2);// hu矩计算Moments mm2 = moments(contours2[0]);Mat hu2;HuMoments(mm2, hu2);// 轮廓匹配for (size_t t = 0; t < contours1.size(); t++) {Moments mm = moments(contours1[t]);Mat hum;HuMoments(mm, hum);double dist = matchShapes(hum, hu2, CONTOURS_MATCH_I1, 0);printf("contour match distance : %.2f\n", dist);if (dist < 1) {printf("draw it \n");Rect box = boundingRect(contours1[t]);rectangle(src, box, Scalar(0, 0, 255), 2, 8, 0);}}imshow("match result", src);
}

最大轮廓与关键点编码

根据二值图像实现轮廓发现,分析每个轮廓并根据面积找到最大轮廓,对最大轮廓使用轮廓逼近,从而得到轮廓编码点。最后绘制编码点信息并显示。

void BinaryAnalysis::max_contour_demo(Mat &image) {// 二值图像Mat mask;inRange(image, Scalar(0, 0, 0), Scalar(110, 110, 110), mask);bitwise_not(mask, mask);// 轮廓发现vector<vector<Point>> contours;vector<Vec4i> hierarchy;findContours(mask, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);int height = image.rows;int width = image.cols;int index = -1;int max = 0;// 最大轮廓寻找for (size_t t = 0; t < contours.size(); t++) {double area = contourArea(contours[t]);if (area > max) {max = area;index = t;}}Mat result = Mat::zeros(image.size(), image.type());Mat pts;drawContours(result, contours, index, Scalar(0, 0, 255), 1, 8);// 关键点编码提取与绘制approxPolyDP(contours[index], pts, 4, true);for (int i = 0; i < pts.rows; i++) {Vec2i pt = pts.at<Vec2i>(i, 0);circle(result, Point(pt[0], pt[1]), 2, Scalar(0, 255, 0), 2, 8, 0);circle(result, Point(pt[0], pt[1]), 2, Scalar(0, 255, 0), 2, 8, 0);}imshow("最大轮廓与关键点编码", result);
}

凸包检测

//轮廓提取凸包
void cv::convexHull(InputArray pointsOutputArray hullbool clockwise = falsebool returnPoints =true//是否返回点集  
)
//判断轮廓是否为凸包
bool cv::isContourConvex(InputArray contour
)//示例代码
void BinaryAnalysis::convex_demo(Mat &image) {vector<vector<Point>> contours;contours_info(image, contours);for (size_t t = 0; t < contours.size(); t++) {vector<Point> hull;convexHull(contours[t], hull);bool isHull = isContourConvex(contours[t]);printf("test convex of the contours %s \n", isHull ? "Y" : "N");int len = hull.size();for (int i = 0; i < hull.size(); i++) {circle(image, hull[i], 4, Scalar(255, 0, 0), 2, 8, 0);line(image, hull[i%len], hull[(i + 1) % len], Scalar(0, 0, 255), 2, 8, 0);}}imshow("凸包检测", image);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/653089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript高级:构造函数

1 引言 构造函数是一种特殊的函数&#xff0c;主要用来初始化对象&#xff1b;常规的 {...} 语法允许创建一个对象&#xff0c;但是通过构造函数可以快速创建多个类似的对象 2 约定 1. 命名以大写字母开头&#xff1b; 2. 它们只能由 “new” 操作符来执行 <script>//…

【C++】filesystem

文章目录 1. 基本配置1.1. VS2019修改C标准1.2. filesystem的引入 2. 日常使用2.1. 认识2.2. 控制台输入路径并对路径进行基本操作 <filesystem>是C 17标准引入的标准库&#xff0c;主要用于处理文件系统的目录和文件操作&#xff0c;接下来总结该库的基本配置和日常使用…

BIGVGAN: A UNIVERSAL NEURAL VOCODER WITHLARGE-SCALE TRAINING——TTS论文阅读

笔记地址&#xff1a;https://flowus.cn/share/a16a61b3-fcd0-4e0e-be5a-22ba641c6792 【FlowUs 息流】Bigvgan 论文地址&#xff1a; BigVGAN: A Universal Neural Vocoder with Large-Scale Training Abstract 背景&#xff1a; 最近基于生成对抗网络&#xff08;GAN&am…

【第十八课】DFS:深度优先搜索( acwing-843 n-皇后问题 / c++代码 )

目录 错误写法(可跳 DFS-剪枝 代码 思路二&#xff1a; 原始解法 错误写法(可跳 看到这道题&#xff0c;我想这不还是n个数的全排列的问题么?也就是把数字变成了字符&#xff0c;一些输出格式上的变化。于是就在原有代码上修改一下应该就行。 我的思路就还是path存有可能…

跨站脚本攻击漏洞概述-XSS

什么是跨站脚本攻击 跨站脚本( Cross-site Scripting ) 攻击&#xff0c;攻击者通过网站注入点注入客户端可执行解析的payload(脚本代码)&#xff0c;当用户访问网页时&#xff0c;恶意payload自动加载并执行&#xff0c;以达到攻击者目的(窃取cookie、恶意传播、钓鱼欺骗等)。…

十大排序算法之非线性时间比较类排序

前言 接下来就开始我们的算法学习之路了&#xff0c;代码会分别使用Java与Python来实现&#xff0c;数据处理的算法很多&#xff0c;排序是最基础且最重要的一类&#xff0c;大多数人都是通过学习排序算法入门的。接下来让我们一起学习闻名遐迩的十大排序算法&#xff0c;它们…

非官方 Bevy 作弊书07-09

源自 网页 Working with 2D - Unofficial Bevy Cheat Book 个人用 有道 翻译&#xff0c;希望能够帮助像我一样的 英语不好 的 bevy 初学者 非官方 Bevy 作弊书 7 使用 bevy 2D 本章涵盖与使用 Bevy 制作 2D 游戏相关的主题。 2D Camera Setup - Unofficial Bevy Cheat Book 非…

【LeetCode: Z 字形变换 + 模拟】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Redis学习——高级篇②

Redis学习——高级篇② Redis7高级之BigKey&#xff08;二&#xff09; 1.MoreKey案例2.BigKey案例2.1 多大算 BigKey以及它的危害2.2 如何产生、发现、删除 3. bigKey生产调优 Redis7高级之BigKey&#xff08;二&#xff09; 1.MoreKe…

【高效开发工具系列】Java读取Html

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Linux系统安装Nginx

一、Nginx的简介 Nginx是一个高性能的HTTP和反向代理web服务器&#xff0c;是由伊戈尔赛索耶夫为俄罗斯访问量第二站点开发的&#xff0c;因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名&#xff0c;第一个公开版本0.1.0发布于2004年10月4日。 Nginx是一…

C# RichTextBox常用属性、方法学习1

1 字体 Font font1 new Font("宋体", 18); richTextBox1.Font font1; Font font2 new Font("宋体", 10, FontStyle.Underline); richTextBox1.SelectionFont font2; 定义字体&#xff0c;可以带2个参数&#…

LeetCode---122双周赛

题目列表 3010. 将数组分成最小总代价的子数组 I 3011. 判断一个数组是否可以变为有序 3012. 通过操作使数组长度最小 3013. 将数组分成最小总代价的子数组 II 一、将数组分成最小总代价的子数组I 这道题纯纯阅读理解题&#xff0c;关键在于理解题意。注意&#xff1a;第一…

总体方差与样本方差的区别是什么?

总体方差和样本方差是统计学中两个重要概念&#xff0c;它们在定义和计算上有所不同&#xff0c;主要区别体现在数据集的性质和计算公式的分母上&#xff1a; 1. 总体方差&#xff08;Population Variance&#xff09;&#xff1a; 定义&#xff1a; 总体方差是指将一个完整数…

嵌入式——窗口看门狗(WWDG)补充

目录 一、独立看门狗与窗口看门狗 1.功能描述 2.两者区别 二、WWDG功能描述 1.窗口看门狗时钟 2.计数器时钟 3. 计数器 4.窗口值 三、WWDG超时时间 一、独立看门狗与窗口看门狗 1.功能描述 STM32有两个看门狗&#xff1a;一个是独立看门狗&#xff08;IWDG&#xff0…

数据结构三:线性表之单链表(带头结点单向)的设计与实现

线性表的链式存储结构正是所谓的单链表&#xff0c;何谓单链表&#xff1f;通过地址将每一个数据元素串起来&#xff0c;进行使用&#xff0c;这可以弥补顺序表在进行任意位置的插入和删除需要进行大量的数据元素移动的缺点&#xff0c;只需要修改指针的指向即可&#xff1b;单…

网络编程套接字(2)

UDP数据报套接字编程 API介绍 DatagramSocket DatagramSocket是UDP的Socket,用于发送和接收数据报. 操作系统中有一类文件,就叫做socket文件(普通文件/目录文件:在硬盘上的) socket文件:抽象的表示了网卡这样的硬件设备 DatagramSocket就是对socket文件进行读写,也就是借助网…

对于gzip的了解

gzip基本操作原理&#xff1a;通过消除文件中的冗余信息&#xff0c;使用哈夫曼编码等算法&#xff0c;将文件体积压缩到最小。这种数据压缩方式在网络传输中发挥了巨大作用&#xff0c;减小了传输数据的大小&#xff0c;从而提高了网页加载速度。 静态资源 Vue Vue CLl修改v…

WordPress如何使用SQL实现一键关闭/开启评论功能(已有评论)

WordPress本人就自带评论功能&#xff0c;不过由于种种原因&#xff0c;有些站长不想开启评论功能&#xff0c;那么应该怎么实现一键关闭评论功能或开启评论功能呢&#xff1f;或者针对已有评论功能的文章进行一键关闭或开启评论功能应该怎么操作&#xff1f; 如果你使用的Wor…

【.NET Core】深入理解C#中的特殊字符

【.NET Core】深入理解C#中的特殊字符 文章目录 【.NET Core】深入理解C#中的特殊字符一、概述二、$-- 字符串内插2.1 内插字符串的结构2.2 内插原始字符串字面量2.3 特殊字符2.4 内插字符串编译 三、-- 逐字字符串标识符四、“”“--原始字符串文本 一、概述 特殊字符是预定义…