OpenCV17-图像形态学操作

OpenCV17-图像形态学操作

  • 1.形态学操作
    • 1.1腐蚀
    • 1.2膨胀
  • 2.形态学应用
    • 2.1开运算
    • 2.2闭运算
    • 2.3形态学梯度
    • 2.4顶帽运算
    • 2.5黑帽运算
    • 2.6击中击不中变换
    • 2.7形态学应用示例


1.形态学操作

1.1腐蚀

图像腐蚀(Image erosion)可用于减小图像中物体的大小、填充孔洞或者分离邻近的物体。腐蚀操作通过对图像中的每个像素应用结构元素(也称为腐蚀内核)来实现。

腐蚀操作的原理是将结构元素与图像进行逐像素的比较。如果结构元素的所有像素与图像中对应位置的像素都匹配,那么该像素保持不变。否则,该像素被腐蚀为背景像素。这样,腐蚀操作将使物体边界向内收缩,并且可以消除小的物体或连接物体之间的细小连接。

下面是一种常见的图像腐蚀算法的伪代码表示:

对于图像中的每个像素(x, y):对于结构元素中的每个像素(i, j):如果结构元素的中心与图像中的像素(x, y)对齐:如果结构元素的所有像素与图像中对应位置的像素都匹配:继续下一步否则:将图像中的像素(x, y)设置为背景像素中断内层循环

腐蚀就是寻找图像中能够将结构元素全部包含的像素点。对于输出图像中的每个像素位置(x, y),将结构元素B的中心与输入图像I的对应位置(x, y)对齐,然后在结构元素B覆盖的区域内选择输入图像中的最小像素值作为输出图像中的像素值。

OpenCV提供了 getStructuringElement() 函数用于生成常用的矩形结构元素、十字结构元素和椭圆结构元素。

Mat getStructuringElement(int shape,  // 生成结构元素的形状Size ksize, // 结构元素的尺寸Point anchor = Point(-1,-1)
);//! shape of the structuring element
enum MorphShapes {MORPH_RECT    = 0, //矩形结构元素,所有元素都为1MORPH_CROSS   = 1, //十字结构元素,中间的列和行元素为1MORPH_ELLIPSE = 2  //椭圆结构元素,矩形的内接椭圆元素为1
};

OpenCV提供了 erode() 函数用于图像腐蚀:

void erode(InputArray src, OutputArray dst, InputArray kernel,  // 结构元素Point anchor = Point(-1,-1), int iterations = 1, // 腐蚀的次数,默认为1int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue() // 使用边界不变外推法时的边界值
);

该函数根据结构元素对输入图像进行腐蚀,在腐蚀多通道图像时,每个通道独立进行腐蚀运算。

需要注意的是,该函数的腐蚀过程只针对图像中的非零像素,因此如果图像是以0像素为背景(黑底),那么腐蚀操作后会看到图像中的内容变得更瘦更小;如果图像是以255像素为背景(白底),那么腐蚀操作后看到的图像中的内容变得更粗更大。(与下面的膨胀相反)

下面代码中演示了腐蚀的效果,实现对原图中米粒进行计数,通过结果可以发现,腐蚀操作可以去除由噪声引起的较小的连通域,得到了正确的米粒数:

#include <opencv2\opencv.hpp>
#include <opencv2/core/utils/logger.hpp> // debug no logusing namespace cv;
using namespace std;//绘制包含区域函数
void drawState(Mat& img, int number, Mat centroids, Mat stats, String str) {RNG rng(10086);vector<Vec3b> colors;for (int i = 0; i < number; i++){//使用均匀分布的随机数确定颜色Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));colors.push_back(vec3);}for (int i = 1; i < number; i++){// 中心位置int center_x = centroids.at<double>(i, 0);int center_y = centroids.at<double>(i, 1);//矩形边框int x = stats.at<int>(i, CC_STAT_LEFT);int y = stats.at<int>(i, CC_STAT_TOP);int w = stats.at<int>(i, CC_STAT_WIDTH);int h = stats.at<int>(i, CC_STAT_HEIGHT);// 中心位置绘制circle(img, Point(center_x, center_y), 2, Scalar(0, 255, 0), 2, 8, 0);// 外接矩形Rect rect(x, y, w, h);rectangle(img, rect, colors[i], 1, 8, 0);putText(img, format("%d", i), Point(center_x, center_y),FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);}imshow(str, img);
}int main()
{cout << "OpenCV Version: " << CV_VERSION << endl;utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//生成用于腐蚀的原图像Mat src = (Mat_<uchar>(6, 6) <<0, 0, 0, 0, 255, 0,0, 255, 255, 255, 255, 255,0, 255, 255, 255, 255, 0,0, 255, 255, 255, 255, 0,0, 255, 255, 255, 255, 0,0, 0, 0, 0, 0, 0);Mat struct1, struct2;struct1 = getStructuringElement(MORPH_RECT, Size(3, 3));  //矩形结构元素struct2 = getStructuringElement(MORPH_CROSS, Size(3, 3));  //十字结构元素Mat erodeSrc;  //存放腐蚀后的图像erode(src, erodeSrc, struct2);namedWindow("src", WINDOW_GUI_NORMAL);namedWindow("erodeSrc", WINDOW_GUI_NORMAL);imshow("src", src);imshow("erodeSrc", erodeSrc);Mat LearnCV_black = imread("black_white_handwritten.jpg", IMREAD_ANYCOLOR);Mat LearnCV_write = imread("white_black_handwritten.jpg", IMREAD_ANYCOLOR);Mat erode_black1, erode_black2, erode_write1, erode_write2;//黑背景图像腐蚀erode(LearnCV_black, erode_black1, struct1);erode(LearnCV_black, erode_black2, struct2);imshow("LearnCV_black", LearnCV_black);imshow("erode_black1", erode_black1);imshow("erode_black2", erode_black2);//白背景腐蚀erode(LearnCV_write, erode_write1, struct1);erode(LearnCV_write, erode_write2, struct2);imshow("LearnCV_write", LearnCV_write);imshow("erode_write1", erode_write1);imshow("erode_write2", erode_write2);//验证腐蚀对小连通域的去除Mat img = imread("rice.png");if (img.empty()){cout << "请确认图像文件名称是否正确" << endl;return -1;}Mat img2;copyTo(img, img2, img);  //克隆一个单独的图像,用于后期图像绘制Mat rice, riceBW;//将图像转成二值图像,用于统计连通域cvtColor(img, rice, COLOR_BGR2GRAY);threshold(rice, riceBW, 50, 255, THRESH_BINARY);Mat out, stats, centroids;//统计图像中连通域的个数int number = connectedComponentsWithStats(riceBW, out, stats, centroids, 8, CV_16U);cout << "未腐蚀:" << number << endl; // 27drawState(img, number, centroids, stats, "未腐蚀时统计连通域");  //绘制图像erode(riceBW, riceBW, struct1);  //对图像进行腐蚀number = connectedComponentsWithStats(riceBW, out, stats, centroids, 8, CV_16U);cout << "腐蚀后:" << number << endl; // 26drawState(img2, number, centroids, stats, "腐蚀后统计连通域");  //绘制图像waitKey(0);return 0;
}

在这里插入图片描述

在这里插入图片描述

1.2膨胀

图像膨胀(Image dilation)是一种图像处理操作,通常用于增加图像中物体的大小或填充物体的空隙,其目标是扩展和增强图像中的图形特征。

在定义结构元素之后,将结构元素的中心点依次放到图像中每一个非零元素处,如果原图中某个元素被结构元素覆盖,但是该像素的像素值不与结构元素中心点对应的像素点的像素值相同,那么将原图中该像素的像素值修改为结构元素中心点对应点的像素值。(将结构元素覆盖的所有区域,修改为1)

OpenCV提供了 dilate() 函数用于图像膨胀。

void dilate(InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1,-1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue()
);

该函数用法同 erode() 。第三个参数是结构元素尺寸,在图像膨胀操作中,结构元素的形状和大小起着关键作用。较大的结构元素将导致更强的膨胀效果,而较小的结构元素则会产生细微的膨胀效果。第五个参数是使用结构元素膨胀的次数,膨胀次数越多效果越明显。

需要注意的是,该函数的膨胀过程只针对图像中的非零像素,因此如果图像是以0像素为背景(黑底),那么膨胀操作后会看到图像中的内容变得更粗和更大;如果图像是以255像素为背景(白底),那么膨胀操作后看到的图像中的内容变得更细和更小。(与上面的腐蚀相反)

下面代码示例,代码最后为了验证膨胀与腐蚀效果之间的关系,求取黑色背景图像的复试结果与白色背景图像的膨胀结果进行逻辑“与”、“异或”运算,证明两个过程的相反性。

#include <opencv2\opencv.hpp>
#include <opencv2/core/utils/logger.hpp> // debug no logusing namespace cv;
using namespace std;int main()
{cout << "OpenCV Version: " << CV_VERSION << endl;utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//生成用于腐蚀的原图像Mat src = (Mat_<uchar>(6, 6) <<0, 0, 0, 0, 255, 0,0, 255, 255, 255, 255, 255,0, 255, 255, 255, 255, 0,0, 255, 255, 255, 255, 0,0, 255, 255, 255, 255, 0,0, 0, 0, 0, 0, 0);Mat struct1, struct2;struct1 = getStructuringElement(0, Size(3, 3));  //矩形结构元素struct2 = getStructuringElement(1, Size(3, 3));  //十字结构元素Mat erodeSrc;  //存放膨胀后的图像dilate(src, erodeSrc, struct2);namedWindow("src", WINDOW_GUI_NORMAL);namedWindow("dilateSrc", WINDOW_GUI_NORMAL);imshow("src", src);imshow("dilateSrc", erodeSrc);Mat LearnCV_black = imread("black_white_handwritten.jpg", IMREAD_ANYCOLOR);Mat LearnCV_write = imread("white_black_handwritten.jpg", IMREAD_ANYCOLOR);if (LearnCV_black.empty() || LearnCV_write.empty()){cout << "请确认图像文件名称是否正确" << endl;return -1;}Mat dilate_black1, dilate_black2, dilate_write1, dilate_write2;//黑背景图像膨胀dilate(LearnCV_black, dilate_black1, struct1);dilate(LearnCV_black, dilate_black2, struct2);imshow("LearnCV_black", LearnCV_black);imshow("dilate_black1", dilate_black1);imshow("dilate_black2", dilate_black2);//白背景图像膨胀dilate(LearnCV_write, dilate_write1, struct1);dilate(LearnCV_write, dilate_write2, struct2);imshow("LearnCV_write", LearnCV_write);imshow("dilate_write1", dilate_write1);imshow("dilate_write2", dilate_write2);//比较膨胀和腐蚀的结果Mat erode_black1, resultXor, resultAnd;erode(LearnCV_black, erode_black1, struct1);bitwise_xor(erode_black1, dilate_write1, resultXor);bitwise_and(erode_black1, dilate_write1, resultAnd);imshow("resultXor", resultXor);imshow("resultAnd", resultAnd);waitKey(0);return 0;
}

在这里插入图片描述

2.形态学应用

图像形态学腐蚀可以将细小的噪声区域去除,但是会将图像主要区域的面积缩小,造成主要区域的形状发生改变。图像形态学膨胀可以扩充每一个区域的面积,填充较小的空洞,但是会增加噪声的面积。根据两者的特性,将图像腐蚀和膨胀适当结合,便可以既去除图像中的噪声,又不缩小图像中主要区域的面积;既填充较小的空洞,又不增加噪声的面积。

2.1开运算

图像开运算可以去除图像中的噪声,消除较小连通域,保留较大连通域,同时能够在两个物体纤细的连接处将两个物体分离,并且在不明显改变较大连通区域面积的同时能够平滑连通域的边界。

开运算:先腐蚀,消除图像中的噪声和较小的连通域;后膨胀,弥补较大的连通域因腐蚀而造成的面积减小。

开运算是对图像腐蚀和膨胀的结合,OpenCV中没有通过只用于图像开运算的函数,而是提供了图像腐蚀和膨胀运算不同组合形式的 morphologyEx() 函数,以实现开运算、闭运算、形态学梯度、顶帽运算、黑帽运算以及击中击不中变换。

void morphologyEx(InputArray src, OutputArray dst,int op,  // 形态学操作类型标志,如下InputArray kernel, // 结构元素Point anchor = Point(-1,-1), int iterations = 1,// 处理次数int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue()
);

该函数根据结构元素对输入图像进行多种形态学操作,在处理多通道图像时,每个通道独立进行处理。

第三个参数是形态学操作类型的标志:

//! type of morphological operation
enum MorphTypes{MORPH_ERODE    = 0, //腐蚀MORPH_DILATE   = 1, //膨胀MORPH_OPEN     = 2, //开运算MORPH_CLOSE    = 3, //闭运算MORPH_GRADIENT = 4, //形态学梯度MORPH_TOPHAT   = 5, //顶帽运算MORPH_BLACKHAT = 6, //黑帽运算MORPH_HITMISS  = 7  //击中击不中bian
};

2.2闭运算

图像闭运算可以去除连通域内的小型空洞,平滑物体轮廓,连接两个临近的连通域。闭运算,先膨胀,填充连通域内小型空洞,扩大连通域边界,将临近的两个连通域连接;后腐蚀,减少由膨胀运算引起的连通域边界的扩大以及面积的增加。

闭运算是对图像膨胀和腐蚀的结合,可以使用 morphologyEx() 函数选择闭运算参数 MORPH_CLOSE 实现闭运算。

2.3形态学梯度

形态学梯度能够描述目标的边界,根据图象腐蚀和膨胀与原图之间的关系计算得到,形态学梯度可以分为基本梯度、内部梯度和外部梯度。

基本梯度:膨胀后图像与腐蚀后图像差值。

内部梯度:原图像与腐蚀后图像差值。

外部梯度:膨胀后图像与原图像差值。

OpenCV提供的 morphologyEx() 函数可以选择形态学梯度参数 MORPH_GRADIENT 实现图像的基本梯度。如果需要计算图像的内部梯度和外部梯度,需要自己通过程序实现。

2.4顶帽运算

顶帽运算是原图像与开运算结果之间的差值,往往用来分离比临近点亮一些的斑块。因为开运算带来的结果是放大了裂缝或者局部低亮度的区域,因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域。

顶帽先对图像进行开运算,之后用原图减去开运算计算的结果。使用 morphologyEx() 函数选择顶帽运算的参数 MORPH_TOPHAT

2.5黑帽运算

与顶帽运算不同,黑帽运算是原图像与闭运算结果之间的差值,往往用来分离比邻近点暗一些的斑块。黑帽运算先对图像进行闭运算,之后从闭运算结果减去原图。使用 morphologyEx() 函数选择黑帽运算的参数 MORPH_BLACKHAT

2.6击中击不中变换

击中击不中变换(Hit-or-Miss Transform)利用两个结构元素,一个称为"击中"元素(Hit element),另一个称为"不中"元素(Miss element)。

击中击不中变换的目的是通过将击中元素与图像进行腐蚀(erosion)操作和将不中元素与图像进行膨胀(dilation)操作,来检测指定形状在图像中的位置。

输出图像中的白色像素表示原始图像中存在与击中元素形状相匹配的区域,黑色像素表示不匹配的区域。

使用 morphologyEx() 函数选择击中击不中变换的参数 MORPH_HITMISS

2.7形态学应用示例

//#include <opencv2/core.hpp>
//#include <opencv2/highgui.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;int main()
{cout << "OpenCV Version: " << CV_VERSION << endl;utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);//用于验证形态学应用的二值化矩阵Mat src = (Mat_<uchar>(9, 12) <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0,0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0,0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0,0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);namedWindow("src", WINDOW_NORMAL);  //可以自由调节显示图像的尺寸imshow("src", src);//3×3矩形结构元素Mat kernel = getStructuringElement(0, Size(3, 3));//对二值化矩阵进行形态学操作Mat open, close, gradient, tophat, blackhat, hitmiss;//对二值化矩阵进行开运算morphologyEx(src, open, MORPH_OPEN, kernel);namedWindow("open", WINDOW_NORMAL);  //可以自由调节显示图像的尺寸imshow("open", open);//对二值化矩阵进行闭运算morphologyEx(src, close, MORPH_CLOSE, kernel);namedWindow("close", WINDOW_NORMAL);  //可以自由调节显示图像的尺寸imshow("close", close);//对二值化矩阵进行梯度运算morphologyEx(src, gradient, MORPH_GRADIENT, kernel);namedWindow("gradient", WINDOW_NORMAL);  //可以自由调节显示图像的尺寸imshow("gradient", gradient);//对二值化矩阵进行顶帽运算morphologyEx(src, tophat, MORPH_TOPHAT, kernel);namedWindow("tophat", WINDOW_NORMAL);  //可以自由调节显示图像的尺寸imshow("tophat", tophat);//对二值化矩阵进行黑帽运算morphologyEx(src, blackhat, MORPH_BLACKHAT, kernel);namedWindow("blackhat", WINDOW_NORMAL);   //可以自由调节显示图像的尺寸imshow("blackhat", blackhat);//对二值化矩阵进行击中击不中变换morphologyEx(src, hitmiss, MORPH_HITMISS, kernel);namedWindow("hitmiss", WINDOW_NORMAL);  //可以自由调节显示图像的尺寸imshow("hitmiss", hitmiss);//用图像验证形态学操作效果Mat keys = imread("keys.jpg", IMREAD_GRAYSCALE);imshow("原图像", keys);threshold(keys, keys, 80, 255, THRESH_BINARY);imshow("二值化后的keys", keys);//5×5矩形结构元素Mat kernel_keys = getStructuringElement(0, Size(5, 5));Mat open_keys, close_keys, gradient_keys, tophat_keys, blackhat_keys, hitmiss_keys;//对图像进行开运算morphologyEx(keys, open_keys, MORPH_OPEN, kernel_keys);imshow("open_keys", open_keys);//对图像进行闭运算morphologyEx(keys, close_keys, MORPH_CLOSE, kernel_keys);imshow("close_keys", close_keys);//对图像进行梯度运算morphologyEx(keys, gradient_keys, MORPH_GRADIENT, kernel_keys);imshow("gradient_keys", gradient_keys);//对图像进行顶帽运算morphologyEx(keys, tophat_keys, MORPH_TOPHAT, kernel_keys);imshow("tophat_keys", tophat_keys);//对图像进行黑帽运算morphologyEx(keys, blackhat_keys, MORPH_BLACKHAT, kernel_keys);imshow("blackhat_keys", blackhat_keys);//对图像进行击中击不中变换morphologyEx(keys, hitmiss_keys, MORPH_HITMISS, kernel_keys);imshow("hitmiss_keys", hitmiss_keys);int k = waitKey(0); // Wait for a keystroke in the windowreturn 0;
}

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

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

相关文章

css之Flex弹性布局(子项常见属性)

文章目录 &#x1f380;前言&#xff1a;本篇博客介绍弹性布局flex容器中子项的常见用法&#x1fa80;flex:子项目占得份数 &#xff08;划分不同子项的比例&#xff09;&#x1f387;align-self 控制单独一个子项在侧轴的排列方式&#x1f9f8;order属性定义子项的排列顺序 &a…

酷开科技 | 酷开系统,为居家生活打开更精彩的窗口

电视在我们的日常生活中扮演着重要的角色。虽然&#xff0c;作为客厅C位的扛把子——电视的娱乐作用深入人心&#xff0c;但是&#xff0c;它的涵义和影响力却因我们每个人的具体生活环境而存在着种种差异&#xff0c;而我们的生活环境又受到我们所处的社会及文化环境的影响。 …

一文了解AIGC与ChatGPT

一、AIGC简介 1.AIGC基础 (1)AIGC是什么 AIGC是人工智能图形计算的缩写&#xff0c;是一种基于图形处理器&#xff08;GPU&#xff09;的计算技术&#xff0c;可以加速各种计算任务&#xff0c;包括机器学习、深度学习、计算机视觉等。 AIGC是一种基于GPU的计算技术&#x…

Git(一)Windows下安装及使用Git Bash

目录 一、简介1.1 什么是Git&#xff1f;1.2 Git 的主要特点1.3 什么是 Git Bash&#xff1f; 二、下载三、安装3.1 同意协议3.2 选择安装位置3.3 其他配置&#xff08;【Next】 即可&#xff09;3.4 安装完毕3.5 打开 Git Bash 官网地址&#xff1a; https://www.git-scm.com/…

包管理工具

代码共享方案 放到npm仓库&#xff0c;下载到本地放到node_modules npm配置文件 必须填写的属性&#xff1a;name、version name是项目的名称&#xff1b; version是当前项目的版本号&#xff1b; description是描述信息&#xff0c;很多时候是作为项目的基本描述&#xff1b…

力扣每日一题61:旋转链表

题目描述&#xff1a; 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3]示例 2&#xff1a; 输入&#xff1a;head [0,1,2], k 4 输…

CSS必学:你需要知道的盒子模型的秘密

作者:WangMin 格言:努力做好自己喜欢的每一件事 CSDN原创文章 博客地址 &#x1f449; WangMin 作为前端开发来说&#xff0c;要掌握的CSS基础一定很多&#xff0c;那么CSS中盒子模型肯定是必考必问必掌握的前端知识点&#xff0c;因为它是CSS基础中非常重要的内容&#xff0c;…

异步编程详解(.NET)

在之前写的一篇关于async和await的前世今生的文章之后&#xff0c;大家似乎在async和await提高网站处理能力方面还有一些疑问&#xff0c;很多网站本身也做了不少的尝试。今天我们再来回答一下这个问题&#xff0c;同时我会做一个async和await在WinForm中的尝试&#xff0c;并且…

Java SOAP 调用 C# 的WebService

Java SOAP 调用 C# 的WebService&#xff0c;C# 的WebService方法的创建可以参考上一篇文章。IntelliJ IDEA Community Edition 2021.2.3的idea64.exe新建项目&#xff0c;导入需要的jar&#xff0c;代码如下&#xff1a; import org.apache.axis.client.Service; import org.…

循环神经网络(Recurrent Neural Network)

1. 为什么需要循环神经网络 RNN 上图是一幅全连接神经网络图&#xff0c;我们可以看到输入层-隐藏层-输出层&#xff0c;他们每一层之间是相互独立地&#xff0c;(框框里面代表同一层)&#xff0c;每一次输入生成一个节点&#xff0c;同一层中每个节点之间又相互独立的话&#…

PKU 概率论+数理统计+建模 期中考复习总结

目录 计算条件概率计算概率&#xff08;放回与不放回&#xff09;生成随机数算法Linear Congruential Method判断是否是full period Uniformity (test of frequency)1.Chi-Square testmethodreminderexample 2.Kolmogorov-Sminov testmethodexample Independence (test of auto…

互联网Java工程师面试题·Spring篇·第一弹

目录 1、一般问题 1.1、不同版本的 Spring Framework 有哪些主要功能&#xff1f; 1.2、什么是 Spring Framework&#xff1f; 1.3、列举 Spring Framework 的优点。 1.4、Spring Framework 有哪些不同的功能&#xff1f; 1.5、Spring Framework 中有多少个模块&#xff…

JSX 模板精简原则

学习目标&#xff1a; 使模板中的逻辑跟简洁 实现&#xff1a; 复杂的多分枝的逻辑收敛为一个函数&#xff0c;通过一个专门的函数来写分支逻辑&#xff0c;模板中只负责调用 实例&#xff1a; // 有一个状态type有1&#xff0c;2&#xff0c;3三种 // 1 展示 h1 // 2 展示 h2…

webpack proxy如何解决跨域?

一、是什么 webpack proxy&#xff0c;即webpack提供的代理服务 基本行为就是接收客户端发送的请求后转发给其他服务器 其目的是为了便于开发者在开发模式下解决跨域问题&#xff08;浏览器安全策略限制&#xff09; 想要实现代理首先需要一个中间服务器&#xff0c;webpac…

C++左值引用与右值引用

0.类型和值类别的区别&#xff1f; 类型&#xff08;type&#xff09;和值类别&#xff08;value category&#xff09; 1.类型指的是数据类型&#xff0c;int&#xff0c;char这样的内置类型&#xff0c;类型主要是用来区别它们的字节大小。除了内置类型还有自定义类型&…

【ESP-BOX-LITE】:照片查看器

目录 项目场景&#xff1a; 项目需求描述&#xff1a; 项目技术&#xff1a; 项目成果&#xff1a; 项目总结&#xff1a; 项目视频&#xff1a; 芳香 项目场景&#xff1a; 使用ESP-BOX-LITE实现照片查看器功能&#xff0c;显示多级目录下的图片或文件夹&#xff0c;自…

二进制部署k8s

常见的K8S安装部署方式 ●Minikube Minikube是一个工具&#xff0c;可以在本地快速运行一个单节点微型K8S&#xff0c;仅用于学习、预览K8S的一些特性使用。 部署地址&#xff1a;https://kubernetes.io/docs/setup/minikube ●Kubeadm Kubeadm也是一个工具&#xff0c;提供…

vue3中使用vue3-pdf-app和使用浏览器内置的PDF插件浏览器PDF文件

文章目录 先准备一个PDF使用浏览器内置的PDF插件预览PDF在HTML中使用浏览器插件预览PDFVscode使用插件发布服务后直接通过URL地址访问PDF可使用的浏览器 在vue3项目中预览PDF文件vue3项目也是可以通过URL地址访问文件的vue3中使用浏览器内置的PDF插件预览PDF代码如下所示&#…

京东数据分析:2023厨房小电市场遇冷,空气炸锅等明星产品被抛弃

过去几年间&#xff0c;宅经济的爆发带火了酸奶机、煮蛋器、豆浆机、空气炸锅、养生壶等&#xff0c;一众外观小巧、功能丰富、价格相对便宜的厨房小家电。但随着年轻人走出家门回归工作岗位&#xff0c;厨房小家电们却步入了艰难时刻。 如今&#xff0c;厨房小家电们似乎正在经…

blender怎么在一个面上对半切割(不影响别的面)

1进入编辑模式 2.在面选择模式下&#xff0c;选中该物体需要切割成两半的面。 3.按K这个快捷键&#xff08;切记&#xff0c;必须得用快捷键&#xff0c;不用的话没办法调出第一个绿色切割点&#xff09;&#xff0c;将切割点移动到需要切割的起始边&#xff0c;按住Shift键不放…