Opencv源码解析(2)算法
目录
一,直方图均衡
1,直方图统计
2,灰度变换
3,直方图均衡
二,可分离滤波器
1,可分离滤波器的工厂
2,ocvSepFilter、sepFilter2D
3,Sobel
三,相位相关法 phaseCorrelate
1,phaseCorrelate
2,汉宁窗
四,匹配器
1,纯虚类DescriptorMatcher
2,子类FlannBasedMatcher
3,knnMatch算法
一,直方图均衡
opencv-4.2.0\modules\imgproc\src\histogram.cpp 中的代码:
1,直方图统计
class EqualizeHistCalcHist_Invoker : public cv::ParallelLoopBody
{
public:enum {HIST_SZ = 256};EqualizeHistCalcHist_Invoker(cv::Mat& src, int* histogram, cv::Mutex* histogramLock): src_(src), globalHistogram_(histogram), histogramLock_(histogramLock){ }void operator()( const cv::Range& rowRange ) const CV_OVERRIDE{int localHistogram[HIST_SZ] = {0, };const size_t sstep = src_.step;int width = src_.cols;int height = rowRange.end - rowRange.start;if (src_.isContinuous()){width *= height;height = 1;}for (const uchar* ptr = src_.ptr<uchar>(rowRange.start); height--; ptr += sstep){int x = 0;for (; x <= width - 4; x += 4){int t0 = ptr[x], t1 = ptr[x+1];localHistogram[t0]++; localHistogram[t1]++;t0 = ptr[x+2]; t1 = ptr[x+3];localHistogram[t0]++; localHistogram[t1]++;}for (; x < width; ++x)localHistogram[ptr[x]]++;}cv::AutoLock lock(*histogramLock_);for( int i = 0; i < HIST_SZ; i++ )globalHistogram_[i] += localHistogram[i];}static bool isWorthParallel( const cv::Mat& src ){return ( src.total() >= 640*480 );}private:EqualizeHistCalcHist_Invoker& operator=(const EqualizeHistCalcHist_Invoker&);cv::Mat& src_;int* globalHistogram_;cv::Mutex* histogramLock_;
};
类继承了ParallelLoopBody,可以做并行加速。
灰度级HIST_SZ = 256
构造函数保存三个参数。
仿函数是统计直方图。
isWorthParallel函数是判断是否启用并行加速。
2,灰度变换
class EqualizeHistLut_Invoker : public cv::ParallelLoopBody
{
public:EqualizeHistLut_Invoker( cv::Mat& src, cv::Mat& dst, int* lut ): src_(src),dst_(dst),lut_(lut){ }void operator()( const cv::Range& rowRange ) const CV_OVERRIDE{const size_t sstep = src_.step;const size_t dstep = dst_.step;int width = src_.cols;int height = rowRange.end - rowRange.start;int* lut = lut_;if (src_.isContinuous() && dst_.isContinuous()){width *= height;height = 1;}const uchar* sptr = src_.ptr<uchar>(rowRange.start);uchar* dptr = dst_.ptr<uchar>(rowRange.start);for (; height--; sptr += sstep, dptr += dstep){int x = 0;for (; x <= width - 4; x += 4){int v0 = sptr[x];int v1 = sptr[x+1];int x0 = lut[v0];int x1 = lut[v1];dptr[x] = (uchar)x0;dptr[x+1] = (uchar)x1;v0 = sptr[x+2];v1 = sptr[x+3];x0 = lut[v0];x1 = lut[v1];dptr[x+2] = (uchar)x0;dptr[x+3] = (uchar)x1;}for (; x < width; ++x)dptr[x] = (uchar)lut[sptr[x]];}}static bool isWorthParallel( const cv::Mat& src ){return ( src.total() >= 640*480 );}private:EqualizeHistLut_Invoker& operator=(const EqualizeHistLut_Invoker&);cv::Mat& src_;cv::Mat& dst_;int* lut_;
};
构造函数保存三个参数。
仿函数是根据灰度变换表lut,把原图变成目标图。
3,直方图均衡
void cv::equalizeHist( InputArray _src, OutputArray _dst )
{CV_INSTRUMENT_REGION();CV_Assert( _src.type() == CV_8UC1 );if (_src.empty())return;CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),ocl_equalizeHist(_src, _dst))Mat src = _src.getMat();_dst.create( src.size(), src.type() );Mat dst = _dst.getMat();CV_OVX_RUN(!ovx::skipSmallImages<VX_KERNEL_EQUALIZE_HISTOGRAM>(src.cols, src.rows),openvx_equalize_hist(src, dst))Mutex histogramLockInstance;const int hist_sz = EqualizeHistCalcHist_Invoker::HIST_SZ;int hist[hist_sz] = {0,};int lut[hist_sz];EqualizeHistCalcHist_Invoker calcBody(src, hist, &histogramLockInstance);EqualizeHistLut_Invoker lutBody(src, dst, lut);cv::Range heightRange(0, src.rows);if(EqualizeHistCalcHist_Invoker::isWorthParallel(src))parallel_for_(heightRange, calcBody);elsecalcBody(heightRange);int i = 0;while (!hist[i]) ++i;int total = (int)src.total();if (hist[i] == total){dst.setTo(i);return;}float scale = (hist_sz - 1.f)/(total - hist[i]);int sum = 0;for (lut[i++] = 0; i < hist_sz; ++i){sum += hist[i];lut[i] = saturate_cast<uchar>(sum * scale);}if(EqualizeHistLut_Invoker::isWorthParallel(src))parallel_for_(heightRange, lutBody);elselutBody(heightRange);
}
先是直方图统计,然后是对于纯色图片的特殊处理(直方图均衡结果等于原图),再是计算灰度变换表lut,最后把原图变成目标图。
二,可分离滤波器
1,可分离滤波器的工厂
Ptr<FilterEngine> createSeparableLinearFilter(int _srcType, int _dstType,InputArray __rowKernel, InputArray __columnKernel,Point _anchor, double _delta,int _rowBorderType, int _columnBorderType,const Scalar& _borderValue)
{Mat _rowKernel = __rowKernel.getMat(), _columnKernel = __columnKernel.getMat();_srcType = CV_MAT_TYPE(_srcType);_dstType = CV_MAT_TYPE(_dstType);int sdepth = CV_MAT_DEPTH(_srcType), ddepth = CV_MAT_DEPTH(_dstType);int cn = CV_MAT_CN(_srcType);CV_Assert( cn == CV_MAT_CN(_dstType) );int rsize = _rowKernel.rows + _rowKernel.cols - 1;int csize = _columnKernel.rows + _columnKernel.cols - 1;if( _anchor.x < 0 )_anchor.x = rsize/2;if( _anchor.y < 0 )_anchor.y = csize/2;int rtype = getKernelType(_rowKernel,_rowKernel.rows == 1 ? Point(_anchor.x, 0) : Point(0, _anchor.x));int ctype = getKernelType(_columnKernel,_columnKernel.rows == 1 ? Point(_anchor.y, 0) : Point(0, _anchor.y));Mat rowKernel, columnKernel;bool isBitExactMode = false;int bdepth = std::max(CV_32F,std::max(sdepth, ddepth));int bits = 0;if( sdepth == CV_8U &&((rtype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&ctype == KERNEL_SMOOTH+KERNEL_SYMMETRICAL &&ddepth == CV_8U) ||((rtype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&(ctype & (KERNEL_SYMMETRICAL+KERNEL_ASYMMETRICAL)) &&(rtype & ctype & KERNEL_INTEGER) &&ddepth == CV_16S)) ){int bits_ = ddepth == CV_8U ? 8 : 0;bool isValidBitExactRowKernel = createBitExactKernel_32S(_rowKernel, rowKernel, bits_);bool isValidBitExactColumnKernel = createBitExactKernel_32S(_columnKernel, columnKernel, bits_);if (!isValidBitExactRowKernel){CV_LOG_DEBUG(NULL, "createSeparableLinearFilter: bit-exact row-kernel can't be applied: ksize=" << _rowKernel.total());}else if (!isValidBitExactColumnKernel){CV_LOG_DEBUG(NULL, "createSeparableLinearFilter: bit-exact column-kernel can't be applied: ksize=" << _columnKernel.total());}else{bdepth = CV_32S;bits = bits_;bits *= 2;_delta *= (1 << bits);isBitExactMode = true;}}if (!isBitExactMode){if( _rowKernel.type() != bdepth )_rowKernel.convertTo( rowKernel, bdepth );elserowKernel = _rowKernel;if( _columnKernel.type() != bdepth )_columnKernel.convertTo( columnKernel, bdepth );elsecolumnKernel = _columnKernel;}int _bufType = CV_MAKETYPE(bdepth, cn);Ptr<BaseRowFilter> _rowFilter = getLinearRowFilter(_srcType, _bufType, rowKernel, _anchor.x, rtype);Ptr<BaseColumnFilter> _columnFilter = getLinearColumnFilter(_bufType, _dstType, columnKernel, _anchor.y, ctype, _delta, bits );return Ptr<FilterEngine>( new FilterEngine(Ptr<BaseFilter>(), _rowFilter, _columnFilter,_srcType, _dstType, _bufType, _rowBorderType, _columnBorderType, _borderValue ));
}
前2个参数是输入输出图像的格式,接下来2个参数是核分离出来的行向量和列向量。
函数返回一个FilterEngine对象,其中保存了一些需要的信息。
2,ocvSepFilter、sepFilter2D
static void ocvSepFilter(int stype, int dtype, int ktype,uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,int width, int height, int full_width, int full_height,int offset_x, int offset_y,uchar * kernelx_data, int kernelx_len,uchar * kernely_data, int kernely_len,int anchor_x, int anchor_y, double delta, int borderType)
{Mat kernelX(Size(kernelx_len, 1), ktype, kernelx_data);Mat kernelY(Size(kernely_len, 1), ktype, kernely_data);Ptr<FilterEngine> f = createSeparableLinearFilter(stype, dtype, kernelX, kernelY,Point(anchor_x, anchor_y),delta, borderType & ~BORDER_ISOLATED);Mat src(Size(width, height), stype, src_data, src_step);Mat dst(Size(width, height), dtype, dst_data, dst_step);f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y));
};
先创建FilterEngine对象,然后调用它的apply方法进行滤波。
void sepFilter2D(int stype, int dtype, int ktype,uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,int width, int height, int full_width, int full_height,int offset_x, int offset_y,uchar * kernelx_data, int kernelx_len,uchar * kernely_data, int kernely_len,int anchor_x, int anchor_y, double delta, int borderType)
{bool res = replacementSepFilter(stype, dtype, ktype,src_data, src_step, dst_data, dst_step,width, height, full_width, full_height,offset_x, offset_y,kernelx_data, kernelx_len,kernely_data, kernely_len,anchor_x, anchor_y, delta, borderType);if (res)return;ocvSepFilter(stype, dtype, ktype,src_data, src_step, dst_data, dst_step,width, height, full_width, full_height,offset_x, offset_y,kernelx_data, kernelx_len,kernely_data, kernely_len,anchor_x, anchor_y, delta, borderType);
}
调用ocvSepFilter
3,Sobel
void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,int ksize, double scale, double delta, int borderType )
{CV_INSTRUMENT_REGION();int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);if (ddepth < 0)ddepth = sdepth;int dtype = CV_MAKE_TYPE(ddepth, cn);_dst.create( _src.size(), dtype );int ktype = std::max(CV_32F, std::max(ddepth, sdepth));Mat kx, ky;getDerivKernels( kx, ky, dx, dy, ksize, false, ktype );if( scale != 1 ){// usually the smoothing part is the slowest to compute,// so try to scale it instead of the faster differentiating partif( dx == 0 )kx *= scale;elseky *= scale;}CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 && ksize == 3 &&(size_t)_src.rows() > ky.total() && (size_t)_src.cols() > kx.total(),ocl_sepFilter3x3_8UC1(_src, _dst, ddepth, kx, ky, delta, borderType));CV_OCL_RUN(ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(),ocl_sepFilter2D(_src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType))Mat src = _src.getMat();Mat dst = _dst.getMat();Point ofs;Size wsz(src.cols, src.rows);if(!(borderType & BORDER_ISOLATED))src.locateROI( wsz, ofs );CALL_HAL(sobel, cv_hal_sobel, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn,ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, dx, dy, ksize, scale, delta, borderType&~BORDER_ISOLATED);CV_OVX_RUN(true,openvx_sobel(src, dst, dx, dy, ksize, scale, delta, borderType))//CV_IPP_RUN_FAST(ipp_Deriv(src, dst, dx, dy, ksize, scale, delta, borderType));sepFilter2D(src, dst, ddepth, kx, ky, Point(-1, -1), delta, borderType );
}
前三个参数是输入图像、输出图像及深度,接下来2个参数是微分的阶。
三,相位相关法 phaseCorrelate
phaseCorrelate函数是利用相位相关法,给两张图片做频域配准。
1,phaseCorrelate
modules\imgproc\src\phasecorr.cpp
cv::Point2d cv::phaseCorrelate(InputArray _src1, InputArray _src2, InputArray _window, double* response)
{CV_INSTRUMENT_REGION();Mat src1 = _src1.getMat();Mat src2 = _src2.getMat();Mat window = _window.getMat();CV_Assert( src1.type() == src2.type());CV_Assert( src1.type() == CV_32FC1 || src1.type() == CV_64FC1 );CV_Assert( src1.size == src2.size);if(!window.empty()){CV_Assert( src1.type() == window.type());CV_Assert( src1.size == window.size);}int M = getOptimalDFTSize(src1.rows);int N = getOptimalDFTSize(src1.cols);Mat padded1, padded2, paddedWin;if(M != src1.rows || N != src1.cols){copyMakeBorder(src1, padded1, 0, M - src1.rows, 0, N - src1.cols, BORDER_CONSTANT, Scalar::all(0));copyMakeBorder(src2, padded2, 0, M - src2.rows, 0, N - src2.cols, BORDER_CONSTANT, Scalar::all(0));if(!window.empty()){copyMakeBorder(window, paddedWin, 0, M - window.rows, 0, N - window.cols, BORDER_CONSTANT, Scalar::all(0));}}else{padded1 = src1;padded2 = src2;paddedWin = window;}Mat FFT1, FFT2, P, Pm, C;// perform window multiplication if availableif(!paddedWin.empty()){// apply window to both images before proceeding...multiply(paddedWin, padded1, padded1);multiply(paddedWin, padded2, padded2);}// execute phase correlation equation// Reference: http://en.wikipedia.org/wiki/Phase_correlationdft(padded1, FFT1, DFT_REAL_OUTPUT);dft(padded2, FFT2, DFT_REAL_OUTPUT);mulSpectrums(FFT1, FFT2, P, 0, true);magSpectrums(P, Pm);divSpectrums(P, Pm, C, 0, false); // FF* / |FF*| (phase correlation equation completed here...)idft(C, C); // gives us the nice peak shift location...fftShift(C); // shift the energy to the center of the frame.// locate the highest peakPoint peakLoc;minMaxLoc(C, NULL, NULL, NULL, &peakLoc);// get the phase shift with sub-pixel accuracy, 5x5 window seems about right here...Point2d t;t = weightedCentroid(C, peakLoc, Size(5, 5), response);// max response is M*N (not exactly, might be slightly larger due to rounding errors)if(response)*response /= M*N;// adjust shift relative to image center...Point2d center((double)padded1.cols / 2.0, (double)padded1.rows / 2.0);return (center - t);
}
前两个参数是传2张图片,第三个是应用窗函数去除图像的边界效应,文档中推荐使用汉宁窗。
2,汉宁窗
void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type)
{CV_INSTRUMENT_REGION();CV_Assert( type == CV_32FC1 || type == CV_64FC1 );CV_Assert( winSize.width > 1 && winSize.height > 1 );_dst.create(winSize, type);Mat dst = _dst.getMat();int rows = dst.rows, cols = dst.cols;AutoBuffer<double> _wc(cols);double* const wc = _wc.data();double coeff0 = 2.0 * CV_PI / (double)(cols - 1), coeff1 = 2.0f * CV_PI / (double)(rows - 1);for(int j = 0; j < cols; j++)wc[j] = 0.5 * (1.0 - cos(coeff0 * j));if(dst.depth() == CV_32F){for(int i = 0; i < rows; i++){float* dstData = dst.ptr<float>(i);double wr = 0.5 * (1.0 - cos(coeff1 * i));for(int j = 0; j < cols; j++)dstData[j] = (float)(wr * wc[j]);}}else{for(int i = 0; i < rows; i++){double* dstData = dst.ptr<double>(i);double wr = 0.5 * (1.0 - cos(coeff1 * i));for(int j = 0; j < cols; j++)dstData[j] = wr * wc[j];}}// perform batch sqrt for SSE performance gainscv::sqrt(dst, dst);
}
四,匹配器
opencv-4.2.0\modules\features2d\src\matchers.cpp中的代码:
1,纯虚类DescriptorMatcher
内含3种匹配算法:
class CV_EXPORTS_W DescriptorMatcher : public Algorithm
{
public:
CV_WRAP void match( InputArray queryDescriptors, InputArray trainDescriptors,CV_OUT std::vector<DMatch>& matches, InputArray mask=noArray() ) const;
CV_WRAP void knnMatch( InputArray queryDescriptors, InputArray trainDescriptors,CV_OUT std::vector<std::vector<DMatch> >& matches, int k,InputArray mask=noArray(), bool compactResult=false ) const;
CV_WRAP void radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors,CV_OUT std::vector<std::vector<DMatch> >& matches, float maxDistance,InputArray mask=noArray(), bool compactResult=false ) const;
CV_WRAP void match( InputArray queryDescriptors, CV_OUT std::vector<DMatch>& matches,InputArrayOfArrays masks=noArray() );
CV_WRAP void knnMatch( InputArray queryDescriptors, CV_OUT std::vector<std::vector<DMatch> >& matches, int k,InputArrayOfArrays masks=noArray(), bool compactResult=false );
CV_WRAP void radiusMatch( InputArray queryDescriptors, CV_OUT std::vector<std::vector<DMatch> >& matches, float maxDistance,InputArrayOfArrays masks=noArray(), bool compactResult=false );
。。。。。。
};
DescriptorMatcher内含纯虚函数clone()
match里面还是调knnMatch,所以实际上是knnMatch和radiusMatch两种算法。
2,子类FlannBasedMatcher
继承DescriptorMatcher
class CV_EXPORTS_W FlannBasedMatcher : public DescriptorMatcher
{
public:CV_WRAP FlannBasedMatcher( const Ptr<flann::IndexParams>& indexParams=makePtr<flann::KDTreeIndexParams>(),const Ptr<flann::SearchParams>& searchParams=makePtr<flann::SearchParams>() );
......
};
(1)clone
创建一个实例
(2)算法
算法没有重载,也没有重写,直接是父类的函数。
3,knnMatch算法
void DescriptorMatcher::knnMatch( InputArray queryDescriptors, InputArray trainDescriptors,std::vector<std::vector<DMatch> >& matches, int knn,InputArray mask, bool compactResult ) const
{CV_INSTRUMENT_REGION();Ptr<DescriptorMatcher> tempMatcher = clone(true);tempMatcher->add(trainDescriptors);tempMatcher->knnMatch( queryDescriptors, matches, knn, std::vector<Mat>(1, mask.getMat()), compactResult );
}
void DescriptorMatcher::knnMatch( InputArray queryDescriptors, std::vector<std::vector<DMatch> >& matches, int knn,InputArrayOfArrays masks, bool compactResult )
{CV_INSTRUMENT_REGION();if( empty() || queryDescriptors.empty() )return;CV_Assert( knn > 0 );checkMasks( masks, queryDescriptors.size().height );train();knnMatchImpl( queryDescriptors, matches, knn, masks, compactResult );
}
核心功能用impl技术存在knnMatchImpl里面了。
相关文章:
Opencv源码解析(2)算法
目录 一,直方图均衡 1,直方图统计 2,灰度变换 3,直方图均衡 二,可分离滤波器 1,可分离滤波器的工厂 2,ocvSepFilter、sepFilter2D 3,Sobel 三,相位相关法 phase…...
让Mac菜单栏变得更加美观整洁——Bartender 5
Bartender 5是一款Mac电脑上的菜单栏图标管理软件,能够帮助您把菜单栏上的图标整理得更加美观、整洁和易于使用。如果您的菜单栏上充斥着许多图标,导致视觉上很不舒适和疲劳,那么Bartender 5就是解决这一问题的最佳选择! Bartend…...
服务器迁移:无缝过渡指南
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
安卓开发中ViewBinding的使用
在安卓开发中,ViewBing 的作用就是简化 findViewById() 代码的写法。 看看下面的替换: etbinding.text //etfindViewById(R.id.text) 下面就看看怎么用的, 首先,打开app模块的build.gradle,然后添加如下代码&…...
【初阶数据结构】树(tree)的基本概念——C语言
目录 一、树(tree) 1.1树的概念及结构 1.2树的相关概念 1.3树的表示 1.4树在实际中的运用(表示文件系统的目录树结构) 二、二叉树的概念及结构 2.1二叉树的概念 2.2现实中真正的二叉树 2.3特殊的二叉树 2.4二叉树的性质…...
二叉树知识点
1.霍夫曼编码 这位作者写的很清楚 哈夫曼编码详解——图解真能看了秒懂_已知字符集abcdef,若各字符出现的次数_Young_IT的博客-CSDN博客 2.满二叉树与完全二叉树 满二叉树是指每层数量是pow(2,n-1)个节点,总节点数是pow(2,n)-1; 而完全二叉树是指最后一层不一定…...
Day69:283. 移动零、11. 盛最多水的容器、42. 接雨水
283. 移动零 leetcode链接:https://leetcode.cn/problems/move-zeroes/ 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。示例 1:…...
tensorrt的安装和使用
安装 提前安装好 CUDA 和 CUDNN,登录 NVIDIA 官方网站下载和主机 CUDA 版本适配的 TensorRT 压缩包即可。 以 CUDA 版本是 10.2 为例,选择适配 CUDA 10.2 的 tar 包,然后执行类似如下的命令安装并测试: #安装c版本 cd /the/pat…...
电压放大器在电子测试中的应用有哪些方面
电压放大器是一种常见的电子设备,广泛应用于各种测试和测量应用中。以下是电压放大器在电子测试中的几个主要方面应用的简要介绍。 信号采集与处理:电压放大器通常用于信号采集和处理,在测试过程中将低电平信号放大到适合进一步处理或分析的水…...
39.地址算术运算
如果p是一个指向数组中某个元素的指针,那么p将会对p进行自增运算并指向下一个元素,而pi将对p进行加i的增量运算,使其指向指针p当前所指向的元素之后的第i个元素。这类运算时指针或地址算术运算中最简单的形式。 allocbuf中的空间使用状况也是…...
没有外网的麒麟系统上搭建GitLab服务并且无需客户端账号密码验证
要在没有外网的麒麟系统上搭建GitLab服务并且无需客户端账号密码验证,可以按照以下步骤进行操作: 安装必要的依赖包和软件 sudo yum install curl policycoreutils-python openssh-server openssh-clients sudo systemctl enable sshd sudo systemctl …...
微服务生态系统:使用Spring Cloud构建分布式系统
文章目录 什么是微服务?为什么选择Spring Cloud?Spring Cloud的关键组件示例:构建一个简单的微服务步骤1:创建Spring Boot项目步骤2:配置Eureka服务发现步骤3:创建REST控制器步骤4:运行项目步骤…...
DIY 一个汽车方向盘游戏外设(MMOS OSW DIY)
OSW-MMOS直驱方向盘DIY过程记录 - 简书 (jianshu.com) DIY 一个汽车方向盘游戏外设(MMOS OSW DIY) 首先讲一下这个直驱系统大概的框架,首先是电脑,电脑里装MMOS的软件(这个软件国内高手把它汉化了的),电脑通过USB线&a…...
校园网络技术需求分析
路由技术: 路由协议工作在 OSI 参考模型的第 3 层,因此它的作用主要是在通信 子网间路由数据包。路由器具有在网络中传递数据时选择最佳路径的能力。 除了可以完成主要的路由任务,利用访问控制列表(Access Control List&#x…...
计算机网络(二):TCP篇
文章目录 1. TCP头部包含哪些内容?2. 为什么需要 TCP 协议? TCP 工作在哪一层?3. 什么是 TCP ?4. 什么是 TCP 连接?5. 如何唯一确定一个 TCP 连接呢?6. UDP头部大小是多少?包含哪些内容…...
测试登录界面:Python
import unittest from selenium import webdriver class LoginTest(unittest.TestCase): def setUp(self): self.driver webdriver.Chrome() def test_login(self): # 打开登录页面 self.driver.get("http://example.com/login") # 输入用户名和密码 user…...
Rust踩雷笔记(7)——两个链表题例子初识裸指针
目录 leetcode 234leetcode 19 leetcode 234 题目在这https://leetcode.cn/problems/palindrome-linked-list/,leetcode 234的回文链表,思路很简单,就是fast和slow两个指针,fast一次移动两个、slow一次一个,最后slow指…...
用什么命令看Linux系统的体系架构
要查看Linux系统的体系架构,可以使用uname命令。在终端中运行以下命令: uname -m该命令将返回系统的体系架构,例如x86_64表示64位系统,i686表示32位系统。 uname 使用方法 uname命令用于获取操作系统的相关信息。它可以用于显示…...
消息中间件大揭秘:选择之前你必须知道的关键信息
Hello大家好!我是小米,很高兴再次和大家见面!今天的话题非常精彩,我们将深入探讨消息中间件,并了解一些常见的消息队列:RabbitMQ、RocketMQ、Kafka以及Redis。如果你正在准备面试,或者只是对这些…...
【Unity基础】4.动画Animation
【Unity基础】4.动画Animation 大家好,我是Lampard~~ 欢迎来到Unity基础系列博客,所学知识来自B站阿发老师~感谢 (一)Unity动画编辑器 (1)Animation组件 这一张我们要学习如何在unity编辑器中&…...
FreeRTOS移植以及核心功能
文章目录 freertos和ucos区别,优缺点比较移植步骤核心功能内存管理(5种内存管理策略)FreeRTOS任务调度算法有三种时间管理通信管理 栈管理 freertos和ucos区别,优缺点比较 FreeRTOS(Free Real-Time Operating System&…...
重装系统(配置环境)
这里写目录标题 0.重装系统1.python1.1 anaconda1.2 pycharm1.3 深度学习环境配置 2.java2.1.安装JDK2.2.配置JDK环境变量2.3IDEA2.4 Maven 3.大数据3.1 虚拟机3.2 Hadoop平台3.3 存储3.4 采集3.5 计算3.6 查询3.7 可视化 0.重装系统 // An highlighted block var foo bar;1.…...
docker系列-报错以及解决指南
1. windows运行docker报错Windows Hypervisor is not presentDocker Desktop is unable to detect a Hypervisor.Hardware assisted virtualization and data execution protection must be enabled in the BIOS. Docker Desktop - Windows Hypervisor is not presentDocker D…...
Vue3快速上手
1.Vue3简介 2020年9月18日,Vue.js发布3.0版本,代号:One Piece(海贼王)耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址:Release v3.0.0 One Piece vuejs/core GitHub 2.Vue3带…...
二叉搜索树(BST,Binary Search Tree)
文章目录 1. 二叉搜索树1.1 二叉搜索树概念1.2 二叉搜索树的查找1.3 二叉搜索树的插入1.4 二叉搜索树的删除 2 二叉搜索树的实现3 二叉搜索树的应用3.1二叉搜索树的性能分析 1. 二叉搜索树 1.1 二叉搜索树概念 二叉搜索树又称二叉排序树,它或者是一棵空树…...
分析key原理
总结: key是虚拟dom对象的标识,当数据发生变化时,vue会根据新数据生成新的虚拟dom,随后vue进行新虚拟dom与旧虚拟dom的差异比较 比较规则: ①旧虚拟dom中找到了与新虚拟dom相同的key 若虚拟dom中的内容没变,…...
[CISCN2019 华东南赛区]Web11 SSTI
这道SSTI 差点给我渗透的感觉了 全是API 我还想去访问API看看 发现这里读取了我们的ip 我们抓包看看是如何做到的 没有东西 我们看看还有什么提示 欸 那我们可不可以直接修改参数呢 我们传递看看 发现成功了 是受控的 这里我就开始没有思路了 于是看了wp 说是ssti 那我们看…...
百度春招C++后端面经总结
这次的面经,主要都是问操作系统、网络编程、C++ 这三大方向。 能明显感觉到,C++面试和Java或者Go面试重点,Java/Go主要是问MySQL、Redis。 一、介绍一下webserver项目 服务器开始运行,创建(初始化)线程池(IO密集型,线程数n+1); 创建 epoll 对连接进行监听 监听到连…...
小程序开发一个多少钱啊
在今天的数字化时代,小程序已经成为一种非常流行的应用程序形式。由于它们的便捷性、易用性和多功能性,小程序吸引了越来越多的用户和企业。但是,很多人在考虑开发一个小程序时,都会遇到同一个问题:开发一个小程序需要…...
C# 随机数生成 Mersenne Twister 马特赛特旋转演算法 梅森旋转算法
NuGet安装MathNet.Numerics 引用: using MathNet.Numerics.Random; /// <summary>/// 包括lower,不包括upper/// </summary>/// <param name"lower"></param>/// <param name"upper"></param>/// <para…...
wordpress 3.9 上传/企业危机公关
SqList.h //函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 //Status是函数的类型,其值是函数结果状态代码 typedef int Status; typedef int…...
如何在网上建设一个公司网站/今日的最新新闻
1、什么是ingress ngress(在kubernetes v1.1时添加)暴露从集群外到集群内服务的HTTP或HTTPS路由。定义在ingress资源上的规则控制流量的路由。 internet|[ Ingress ]--|-----|--[ Services ] 一个ingress可以配置用于提供外部可访问的服务url、负载均衡…...
wordpress 整站转移/网络营销渠道可分为
背景服务器的某个模块的进程莫名其妙的不见了,查看MQ的连接情况,该模块的连接数直接为0,但是其他模块的进程还存在。很是纳闷该模块的进程为什么进程突然不见了。查看进程的log文件,没有发现有stop信号收到。平时停止会收到kill信…...
网站建设费用明细报价/凡科建站下载
2023年司法考试分为主观题和客观题,报名需要具备全日制普通高等学校法学类本科学历并获得学士及以上学位,非法学毕业也可以考。 司法考试2023年报考条件 符合以下条件人员,可报名参加司法考试: 1.具有中华人民共和国国籍; 2.坚决拥…...
wordpress分页出现404/友情链接建立遵循的原则包括
可以用抽象工厂模式来造车。 车的品牌有很多,而且车的属性也不少,比如车的类型、排量、门的数量,等等。可以提炼出有关车的一个抽象类: public abstract class Car{public string Model { get; set; }public string Engine { get;…...
花店网站建设毕设介绍/电子商务平台
2009年,华晨汽车在德国的Euro NCAP标准碰撞测试中成绩糟糕,成为当年中国汽车业的典型事件。“碰撞门”后的沈阳华晨金杯汽车正视问题,对自主品牌遇到这种挫折,抑或是一种壁垒,但公司承认与和世界发达国家的一些企业有很…...