OpenCV_距离变换的图像分割和Watershed算法详解

在学习watershed算法的时候,书写代码总会出现一些错误:

上述代码运行报错,显示OpenCV(4.10.0) Error: Assertion failed (src.type() == CV_8UC3 && dst.type() == CV_32SC1) in cv::watershed

查找资料:目前已解决

这个错误明确指出是在  watershed  函数中输入的参数类型不匹配。根据错误信息,要求  src (即  image  )的类型是  CV_8UC3  , dst (即  markers  )的类型是  CV_32SC1  。
 
您需要确保  image  是 8 位无符号的 3 通道彩色图像,并且  markers  是 32 位有符号的单通道矩阵。
 
请检查以下几点:
 
1.  image  的初始化和类型是否正确。
2.  markers  的创建和后续操作是否保持了  CV_32SC1  类型。
 
如果问题仍然存在,请提供更多关于  image  的初始化和加载的代码部分,以便更准确地帮助您找到问题所在。

分水岭算法

分水岭算法的基本原理为:将任意的灰度图像视为地形图表面,其中灰度值高的部分表示山峰和丘陵,而灰度值低的地方表示山谷。用不同颜色的水(标签)填充每个独立的山谷(局部最小值);随着水平面的上升,来自不同山谷(具有不同颜色)的水将开始合并。为了避免出现这种情况,需要在水汇合的位置建造水坝;持续填充水和建造水坝,直到所有的山峰和丘陵都在水下。整个过程中建造的水坝将作为图像分割的依据。

使用分水岭算法执行图像分割操作时通常包含下列步骤:
(1) 加载源图像并检查是否加载没有任何问题,然后显示
(2) 将原图转换为灰度图像,然后显示
(3) 应用形态学变换中的开运算和膨胀操作,去除图像噪声,获取图像边缘信息,确定图像背景
(4) 显示矩阵marks(只为显示,可省略)
(5) 执行分水岭算法分割图像
(6) 对每一个区域进行颜色填充
(7) 跟原始图像融合
//生成随机颜色函数
Vec3b randomColor(int value);
Vec3b randomColor(int value) {value = value % 255;RNG rng;int aa = rng.uniform(0, value);int bb = rng.uniform(0, value);int cc = rng.uniform(0, value);return Vec3b(aa, bb, cc);
}
void QuickDemo::thirtyFive(Mat& image) {//灰度化,滤波,Canny边缘检测Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);GaussianBlur(gray, gray, Size(5, 5), 2);Canny(gray, gray, 80, 150);//imshow("gray", gray);//查找轮廓vector<vector<Point>>contours;vector<Vec4i>hierarchy;findContours(gray, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());Mat contoursImage = Mat::zeros(image.size(), CV_8UC1);//轮廓	Mat marks(image.size(), CV_32S); //Opencv分水岭第二个矩阵参数marks = Scalar::all(0);//int index = 0;//int compCount = 0;for (size_t i = 0; i < contours.size(); i++){//对marks进行标记,对不同区域的轮廓进行编号,相当于设置注水点,有多少轮廓,就有多少注水点drawContours(marks, contours, i, Scalar::all(i + 1), 1, 8, hierarchy);drawContours(contoursImage, contours, i, Scalar(255), 1, 8, hierarchy);}//我们来看一下传入的矩阵marks里是什么东西//Mat marksShows;//convertScaleAbs(marks,marksShows);//imshow("marksShows", marksShows);//imshow("contoursImage", contoursImage);watershed(image, marks);//我们再来看一下分水岭算法之后的矩阵marks里是什么东西Mat afterwatershed;convertScaleAbs(marks, afterwatershed);//imshow("afterwatershed", afterwatershed);//对每一个区域进行颜色填充Mat perspectiveImage = Mat::zeros(image.size(), CV_8UC3);for (size_t i = 0; i < marks.rows; i++){for (size_t j = 0; j < marks.cols; j++){int index = marks.at<int>(i, j);if (index == -1) {perspectiveImage.at<Vec3b>(i, j) = Vec3b(255, 255, 255);}else {perspectiveImage.at<Vec3b>(i, j) = randomColor(index);}}}imshow("perspectiveImage", perspectiveImage);//分割并填充颜色的结果跟原始图像融合Mat wshed;addWeighted(image, 0.4, perspectiveImage, 0.6, 0, wshed);imshow("wshed", wshed);}

说明/结果

1.加载源图像并检查是否加载没有任何问题,然后显示:

2.将原图转换为灰度图像,然后显示:

Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("gray", gray);

3.应用形态学变换中的开运算和膨胀操作,去除图像噪声,获取图像边缘信息,确定图像背景

GaussianBlur(gray, gray, Size(5, 5), 2);
Canny(gray, gray, 80, 150);
imshow("gray", gray);//查找轮廓
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
findContours(gray, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());Mat contoursImage = Mat::zeros(image.size(), CV_8UC1);//轮廓	
Mat marks(image.size(), CV_32S); //Opencv分水岭第二个矩阵参数
marks = Scalar::all(0);
//int index = 0;
//int compCount = 0;
for (size_t i = 0; i < contours.size(); i++)
{//对marks进行标记,对不同区域的轮廓进行编号,相当于设置注水点,有多少轮廓,就有多少注水点drawContours(marks, contours, i, Scalar::all(i + 1), 1, 8, hierarchy);drawContours(contoursImage, contours, i, Scalar(255), 1, 8, hierarchy);
}
imshow("contoursImage", contoursImage);

4.显示矩阵marks(只为显示,可省略)

//我们来看一下传入的矩阵marks里是什么东西
Mat marksShows;
convertScaleAbs(marks,marksShows);
imshow("marksShows", marksShows);

5.执行分水岭算法分割图像

watershed(image, marks);
//我们再来看一下分水岭算法之后的矩阵marks里是什么东西
Mat afterwatershed;
convertScaleAbs(marks, afterwatershed);
imshow("afterwatershed", afterwatershed);

6.对每一个区域进行颜色填充

//生成随机颜色函数
Vec3b randomColor(int value);
Vec3b randomColor(int value) {value = value % 255;RNG rng;int aa = rng.uniform(0, value);int bb = rng.uniform(0, value);int cc = rng.uniform(0, value);return Vec3b(aa, bb, cc);
}
//对每一个区域进行颜色填充
Mat perspectiveImage = Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < marks.rows; i++)
{for (size_t j = 0; j < marks.cols; j++){int index = marks.at<int>(i, j);if (index == -1) {perspectiveImage.at<Vec3b>(i, j) = Vec3b(255, 255, 255);}else {perspectiveImage.at<Vec3b>(i, j) = randomColor(index);}}
}
imshow("perspectiveImage", perspectiveImage);

7.跟原始图像融合

Mat wshed;
addWeighted(image, 0.4, perspectiveImage, 0.6, 0, wshed);
imshow("wshed", wshed);

距离变换实现分水岭算法

实现步骤:
1.输入图像
2.灰度化
3.二值化
4.执行距离变换
5.归一化
6.二值化
7.生成marker:通过findContours+drawContours来创建一个marker
8.将7生成的marker放入分水岭函数:watershed
9.给marker着色
10.输出着色后的图像
此算法关键点在于生成marker。生成marker之后其实已经完成了算法,后面的着色只是为了让输出更加好看。
void QuickDemo::thirtyFour(Mat& image) {Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);Mat binary;threshold(gray, binary, 175, 255, THRESH_BINARY);//imshow("binary image ",bw);Mat dist;distanceTransform(binary, dist, DIST_L2, 3);normalize(dist, dist, 0, 1, NORM_MINMAX);threshold(dist, dist, 0.1, 1, THRESH_BINARY);normalize(dist, dist, 0, 255, NORM_MINMAX);dist.convertTo(dist, CV_8UC1);imshow("distanceTransform", dist);vector<vector<Point>>contours;findContours(dist, contours, RETR_CCOMP, CHAIN_APPROX_SIMPLE, Point());vector<Vec4i>hierarchy;Mat markers(dist.size(), CV_8U); //Opencv分水岭第二个矩阵参数markers = Scalar::all(0);for (size_t i = 0; i < contours.size(); i++){drawContours(markers, contours, i, Scalar::all(i + 1), -1, 8, hierarchy, INT_MAX);}circle(markers, Point(3, 3), 3, Scalar(255), -1);//imshow("markers", markers*20);image.convertTo(image, CV_8UC3);markers.convertTo(markers, CV_32SC1);watershed(image, markers);markers.convertTo(markers, CV_8UC1);imshow("markers", markers*50);RNG rng(12345);vector<Vec3b>colors;for (size_t i = 0; i < contours.size(); i++){int r = rng.uniform(0, 255);int g = rng.uniform(0, 255);int b = rng.uniform(0, 255);colors.push_back(Vec3b(r, g, b));}//给marker着色Mat finalResult = Mat::zeros(dist.size(), CV_8UC3);//三通道彩色图像int index = 0;for (int row = 0; row < markers.rows; row++) {for (int col = 0; col < markers.cols; col++) {index = markers.at<uchar>(row, col);if (index > 0 && index <= contours.size()) {finalResult.at<Vec3b>(row, col) = colors[index - 1];}else {finalResult.at<Vec3b>(row, col) = Vec3b(255, 255, 255);}}}imshow("finalResult", finalResult);}

说明/结果

1. 输入图像并显示

2.获取灰度图像并显示

Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("gray image ", gray);

3.获取二值图像并显示

Mat binary;
threshold(gray, binary, 175, 255, THRESH_BINARY);
imshow("binary image ", binary);

4.执行距离变换归一化,并显示

Mat dist;
distanceTransform(binary, dist, DIST_L2, 3);
normalize(dist, dist, 0, 1, NORM_MINMAX);
imshow("dist image ", dist);

5.进行二值变换归一化,并显示

threshold(dist, dist, 0.1, 1, THRESH_BINARY);
normalize(dist, dist, 0, 255, NORM_MINMAX);
dist.convertTo(dist, CV_8UC1);
imshow("distanceTransform", dist);

6.生成marker:通过findContours+drawContours来创建一个marker

vector<vector<Point>>contours;
findContours(dist, contours, RETR_CCOMP, CHAIN_APPROX_SIMPLE, Point());
vector<Vec4i>hierarchy;
Mat markers(dist.size(), CV_8U); //Opencv分水岭第二个矩阵参数
markers = Scalar::all(0);
for (size_t i = 0; i < contours.size(); i++)
{drawContours(markers, contours, i, Scalar::all(i + 1), -1, 8, hierarchy, INT_MAX);
}
circle(markers, Point(3, 3), 3, Scalar(255), -1);
imshow("markers", markers*20);

7.将7生成的marker放入分水岭函数:watershed

image.convertTo(image, CV_8UC3);
markers.convertTo(markers, CV_32SC1);
watershed(image, markers);
markers.convertTo(markers, CV_8UC1);
imshow("markers", markers*50);

8.给marker着色,并输出着色后的图像

RNG rng(12345);
vector<Vec3b>colors;
for (size_t i = 0; i < contours.size(); i++)
{int r = rng.uniform(0, 255);int g = rng.uniform(0, 255);int b = rng.uniform(0, 255);colors.push_back(Vec3b(r, g, b));	
}
//给marker着色
Mat finalResult = Mat::zeros(dist.size(), CV_8UC3);//三通道彩色图像
int index = 0;
for (int row = 0; row < markers.rows; row++) {for (int col = 0; col < markers.cols; col++) {index = markers.at<uchar>(row, col);if (index > 0 && index <= contours.size()) {finalResult.at<Vec3b>(row, col) = colors[index - 1];}else {finalResult.at<Vec3b>(row, col) = Vec3b(255, 255, 255);}}
}
imshow("finalResult", finalResult);

9.跟原始图像融合

Mat wdst;
addWeighted(finalResult,0.6,image,0.4,0, wdst);
imshow("wdst", wdst);

threshold函数

threshold( InputArray src, OutputArray dst, double thresh, double maxval,type 
);
//参数1:输入的灰度图像
//参数2:输出图像
//参数3:进行阈值操作时阈值的大小
//参数4:设定的最大灰度值(该参数运用在二进制与反二进制阈值操作中)
//参数5:阈值的类型。从下面提到的5种中选择出的结果
THRESH_BINARY=0: 二进制阈值
THRESH_BINARY_INV=1: 反二进制阈值
THRESH_TRUNC=2: 截断阈值
THRESH_TOZERO=3: 0阈值
THRESH_TOZERO_INV=4: 反0阈值
THRESH_OTSU=8   自适应閾值

(1)正向二值化,THRESH_BINARY

正向二值化,如果当前的像素值大于设置的阈值(thresh),则将该点的像素值设置为maxval;否则,将该点的像素值设置为0;

(2)反向二值化,THRESH_BINARY_INV

反向二值化,如果当前的像素值大于设置的阈值(thresh),则将该点的像素值设置为0;否则,将该点的像素值设置为maxval

(3)THRESH_TRUNC

如果当前的像素值大于设置的阈值(thresh),则将该点的像素值设置为threshold;否则,将该点的像素值不变

(4)THRESH_TOZERO

如果当前的像素值大于设置的阈值(thresh),则将该点的像素值不变;否则,将该点的像素值设置为0

THRESH_TOZERO_INV

如果当前的像素值大于设置的阈值(thresh),则将该点的像素值设置为0;否则,将该点的像素值不变

adaptiveThreshold函数

void adaptiveThreshold(InputArray src,OutputArray dst,double maxValue,int adaptiveMethod,int thresholdType,int blockSize,double C
);
第一个参数,InputArray src,原图,即输入图像,是一个8位单通道的图像;
第二个参数,OutputArray dst,目标图像,与原图像具有同样的尺寸与类型;
第三个参数,double maxValue,分配给满足条件的像素的非零值;
第四个参数,int adaptiveMethod,自适应阈值的方法,通常有以下几种方法;ADAPTIVE_THRESH_MEAN_C,阈值T(x,y)是(x,y)减去C的Blocksize×Blocksize
邻域的平均值。ADAPTIVE_THRESH_GAUSSIAN_C ,阈值T(x,y)是(x,y)减去C的Blocksize×Blocksize
邻域的加权和(与高斯相关),默认sigma(标准差)用于指定的Blocksize;具体的情况可以参见getGaussianKernel函数;
第五个参数,int thresholdType,阈值的类型必须是以下两种类型,THRESH_BINARY,正向二值化THRESH_BINARY_INV ,反向二值化
第六个参数,int blockSize,计算blocksize x blocksize大小的领域内的阈值,必须为奇数,
例如,3,5,7等等,一般二值化使用21,31,41;
第七个参数,double C,从平均数或加权平均数减去常量。通常,它是正的,但也可能是零或负数。
二值化时使用的7。
补充
函数cvAdaptiveThreshold的确可以将灰度图像二值化,但它的主要功能应该是边缘提取,
关键是里面的block_size参数,该参数是决定局部阈值的block的大小
1)当block很小时,如block_size=3 or 5 or 7时,“自适应”的程度很高,
即容易出现block里面的像素值都差不多,这样便无法二值化,而只能在边缘等梯度大的地方实现二值化
,结果显得它是边缘提取函数;
2)当把block_size设为比较大的值时,如block_size=21 or 31 or 41时,cvAdaptiveThreshold便是
二值化函数了;
3)src与dst 这两个都要是单通道的图像。

findContours函数

void findContours (InputOutputArray      image,       // 输入图像OutputArrayOfArrays   contours,    // 检测到的轮廓OutputArray           hierarchy,   // 可选的输出向量int       mode,            
// 轮廓获取模式 (RETR_EXTERNAL, RETR_LIST, RETR_CCOMP,RETR_TREE, RETR_FLOODFILL)int       method,          
// 轮廓近似算法 (CHAIN_APPROX_NONE, CHAIN_APPROX_SIMPLE, CHAIN_APPROX_TC89_L1, CHAIN_APPROX_TC89_KCOS)Point     offset = Point() // 轮廓偏移量
)hierarchy 为可选的参数,如果不选择该参数,则可得到 findContours 函数的第二种形式
void findContours (InputOutputArray   image,OutputArrayOfArrays contours,int    mode,int    method,Point   offset = Point()
)drawContours() 函数如下: 
void drawContours (InputOutputArray     image,         // 目标图像InputArrayOfArrays   contours,      // 所有的输入轮廓int               contourIdx,      //const Scalar &     color,           //  轮廓颜色int          thickness = 1,         //  轮廓线厚度int          lineType = LINE_8,     //InputArray   hierarchy = noArray(), //int          maxLevel = INT_MAX,    //Point        offset = Point()       //    
)

 watershed函数

watershed(src,markers);
src:原图像
markers:目标markers,生成markers是通过findContours边沿查找+drawContours来实现的。
ps:这一步非常重要,有了marker就可以使用分水岭算法了。

distanceTransform函数 

distanceTransform()距离变换的定义是计算一个图像中非零像素点到最近的零像素点的
距离,也就是到零像素点的最短距离。即距离变换的定义是计算一个图像中非零像素点到
最近的零像素点的距离,也就是到零像素点的最短距离。
通常处理的是一个二值化的图,所以求距离可以归一化,距离(像素距离)单位为1。
void distanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize, int dstType=CV_32F )
void distanceTransform(InputArray src, OutputArray dst, OutputArray labels, int distanceType, int maskSize, int labelType=DIST_LABEL_CCOMP )
src:源矩阵
dst:目标矩阵
distanceType:距离类型。可以的类型是CV_DIST_L1、CV_DIST_L2、CV_DIST_C,具体各
类型的意义,请查阅相关算法文档。
maskSize:距离变换运算时的掩码大小。值可以是3、5或CV_DIST_MASK_PRECISE
(5或CV_DIST_MASK_PRECISE只能用在第一个原型中)。
当distanceType=CV_DIST_L1 或 CV_DIST_C时,maskSize只能为3。
dstType:输出图像(矩阵)的类型,可以是CV_8U 或 CV_32F。CV_8U只能用在第一个原型中,
而且distanceType只能为CV_DIST_L1。
labels:输出二维阵列标签。
labelType:标签数组类型。可选值为DIST_LABEL_CCOMP和DIST_LABEL_PIXEL

原图片

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

CentOS7搭建Hadoop3集群教程

一、集群环境说明 1、用VMware安装3台Centos7虚拟机 2、虚拟机配置&#xff1a;2C&#xff0c;2G内存&#xff0c;50G存储 3、集群架构设计 从表格中&#xff0c;可以看出&#xff0c;Hadoop集群&#xff0c;主要有2个模块服务&#xff0c;一个是HDFS服务&#xff0c;一个是YAR…

wordpress更换域名后用户图片头像不显示

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

【Python报错已解决】AttributeError: ‘DataFrame‘ object has no attribute ‘append‘

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

基于深度学习的文本情感原因提取研究综述——论文阅读

前言 既然要学习情感分析&#xff0c;那么肯定还要了解情感原因对抽取的发展历程&#xff0c;所以我又搜了一篇研究综述&#xff0c;虽然是2023年发表的&#xff0c;但是里面提及到的历程仅停留到2022年。这篇综述发布在TASLP期刊&#xff0c;是音频、声学、语言信号处理的顶级…

【论文解读系列】用于自监督点云表示的生成变分对比学习

Generative Variational-Contrastive Learning for Self-Supervised Point Cloud Representation | IEEE Transactions on Pattern Analysis and Machine Intelligence (acm.org) 作者&#xff1a;Bohua Wang; Zhiqiang Tian; Aixue Ye; Feng Wen; Shaoyi Du; Yue Gao 摘要 三…

Coggle数据科学 | 科大讯飞AI大赛:玉米雄穗识别挑战赛

本文来源公众号“Coggle数据科学”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;科大讯飞AI大赛&#xff1a;玉米雄穗识别挑战赛 赛题名称&#xff1a;玉米雄穗识别挑战赛 赛题类型&#xff1a;计算机视觉、物体检测 赛题任务&…

LeetCode_sql_day30(1264.页面推荐)

描述 1264.页面推荐 朋友关系列表&#xff1a; Friendship ------------------------ | Column Name | Type | ------------------------ | user1_id | int | | user2_id | int | ------------------------ (user1_id, user2_id) 是这张表具有唯一值的…

HT326 免电感滤波2x20W D类立体声音频功放

特点 输出功率(BTL模式) 2x20W (VDD14.5V,RL4Ω,THDN1%) 单电源系统: 4.5V-18V; 超过90%效率&#xff0c;无需散热器 扩频功能&#xff0c;免电感滤波 模拟差分/单端输入可选 增益:32dB 保护功能:过压/过流/过热/欠压异常&#xff0c;直流检测 和短路保护 无铅无卤封装&#x…

Python画笔案例-054 绘制流光溢彩动画

1、绘制流光溢彩动画 通过 python 的turtle 库绘制 流光溢彩动画&#xff0c;如下图&#xff1a; 2、实现代码 绘制流光溢彩动画&#xff0c;以下为实现代码&#xff1a; """本程序实现流光溢彩的动画效果 """ from turtle import * from color…

流动网红打卡车!苏州金龙海格双层巴士带你体验别样津门津韵

近日&#xff0c;由文化和旅游部主办&#xff0c;天津市文化和旅游局等单位承办的2024中国文化旅游产业博览会在天津拉开帷幕&#xff0c;展会期间&#xff0c;来自全国各地的文旅产品精彩亮相。而在天津交通集团展台&#xff0c;来自苏州金龙海格客车制造的网红双层观光“音乐…

YOLOv8改进 - 注意力篇 - 引入ECA注意力机制

一、本文介绍 作为入门性第一篇&#xff0c;这里介绍了ECA注意力在YOLOv8中的使用。包含ECA原理分析&#xff0c;ECA的代码、ECA的使用方法、以及添加以后的yaml文件及运行记录。 二、ECA原理分析 ECA官方论文地址&#xff1a;ECA文章 ECA的pytorch版代码&#xff1a;ECA的…

Unet改进41:添加gConvBlock(2024最新改进方法)|

本文内容:在不同位置添加gConvBlock 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 图像去雾是低层次视觉中的一个活跃话题,随着深度学习的快速发展,许多图像去雾网络被提出。尽管这些网络的管道运行良好,但改善图像去雾性能的关键机制仍不清楚。因此…

[Simpfun游戏云1]搭建MC Java+基岩互通生存游戏服务器

众所周知&#xff0c;MC有多个客户端&#xff0c;像常见的比如Java Edition和基岩等&#xff0c;这就导致&#xff0c;比如我知道一个超级好玩的JE服务器&#xff0c;但我又想使用基岩版来玩&#xff0c;肯定是不行的&#xff0c;因为通讯协议不一样。 这就有一些人才发明了多…

【linux】4张卡,坏了1张,怎么办?

先禁用这张卡 grub 禁用&#xff0c;防止加载驱动 禁用这张卡的 PCI # 禁用 PCI 设备 0000:b1:00.0 (NVIDIA GPU) ACTION"add", SUBSYSTEM"pci", ATTR{vendor}"0x10de", KERNELS"0000:b1:00.0", RUN"/bin/sh -c echo 0000:b1:00…

javaseday28 IO

IO流 IO流;存储和读取数据的解决方案。 纯文本文件&#xff1a;Windows自带的记事本打开能读懂的文件&#xff0c;word和Excel不是纯文本文件&#xff0c;txt和md是纯文本文件。 小结 IO流体系 FileOutputStream public class Demo1 {public static void main(String[] args)…

Ping32加密利器 vs ipguard,企业数据防护的实战对比

在数字化时代&#xff0c;企业数据的安全防护已成为不可忽视的重要议题。随着数据泄露事件的频发&#xff0c;企业迫切需要采用高效、可靠的数据防泄漏解决方案来保护其敏感信息。Ping32和IP-Guard作为市场上备受瞩目的两款数据保护工具&#xff0c;各自以其独特的功能和优势赢…

深入分析几个难以理解的Comparator源码

1.分析comparing单参数方法 网上很多帖子说实话&#xff0c;不咋地&#xff0c;讲的不细节&#xff0c;抄来抄去&#xff0c;就让我这个大二的垃圾&#xff0c;给大家梳理一下Comparator这几个难以理解public static方法吧。 1.1函数式接口Function 这个函数是使用的函数式编程…

OrCAD使用,快捷键,全选更改封装,导出PCB网表

1 模块名称 2 快捷键使用 H: 镜像水平 V&#xff1a;镜像垂直 R: 旋转 I: 放大 O&#xff1a; 放小 P&#xff1a;放置元器件 W&#xff1a; 步线 B&#xff1a; 总线&#xff08;无电气属性&#xff09; E: 总线连接符&#xff08;和BUS一起用&#xff09…

图的应用(关键路径)

基于你设计的带权有向无环图&#xff0c;写出所有合法的关键路径&#xff0c;并算出关键路径总长度 文字描述&#xff1a;关键路径总长度的现实意义是什么&#xff1f; 1.关键路径 总长度454316 2.现实意义 从源点到汇点的所有路径中&#xff0c;具有最大路径长度的路径称…

如何选择OS--Linux不同Distribution的选用

写在前言&#xff1a; 刚写了Windows PC的不同editions的选用&#xff0c;趁热&#xff0c;把Linux不同的Distribution选用也介绍下&#xff0c;希望童鞋们可以了解-->理解-->深入了解-->深入理解--...以致于能掌握特定版本的Linux的使用甚者精通。……^.^…… so&a…