8.5LoG算子边缘检测

news2024/11/15 13:58:51

LoG的基本概念

LoG(Laplacian of Gaussian)算子是一种结合了高斯模糊和平滑处理的边缘检测方法。它通过先对图像应用高斯滤波器来去除噪声,然后再对结果应用拉普拉斯算子来检测边缘。LoG算子的主要优点是可以检测图像中的边缘和其他重要特征,同时减少噪声的影响。

LoG算子原理

LoG算子的基本思想是先使用高斯滤波器对图像进行平滑处理,然后再应用Laplacian算子。高斯滤波器可以去除图像中的噪声,而Laplacian算子则可以检测图像中的边缘。LoG算子可以看作是Laplacian算子与高斯核的卷积。
LoG算子结合了高斯平滑和拉普拉斯算子的优点。高斯平滑可以有效去除图像中的噪声,而拉普拉斯算子则能够检测图像中的边缘。

LoG算子的操作可以分为两步:

1.高斯平滑:使用高斯核对图像进行卷积,以去除噪声。
2.拉普拉斯算子:对平滑后的图像应用拉普拉斯算子,以检测边缘。

在OpenCV中,可以先使用cv::GaussianBlur对图像进行高斯平滑处理,然后使用cv::Laplacian进行拉普拉斯变换。但是,为了直接使用LoG算子,可以预先计算一个LoG核,然后使用cv::filter2D函数进行卷积操作。

示例代码1

以下是一个使用OpenCV C++实现LoG边缘检测的示例代码:

#include <opencv2/opencv.hpp>
#include <iostream>

int main(int argc, char** argv)
{
    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " <Image Path>" << std::endl;
        return -1;
    }

    // 读取图像
    cv::Mat src = cv::imread(argv[1], cv::IMREAD_GRAYSCALE);

    if (!src.data) {
        std::cout << "Error: Image cannot be loaded!" << std::endl;
        return -1;
    }

    // 定义高斯核的尺寸和标准差
    int kernel_size = 5; // 一般选择奇数
    double sigma = 1.4; // 高斯核的标准差

    // 构建LoG核
    cv::Mat log_kernel = cv::getGaussianKernel(kernel_size, sigma, CV_32F);
    cv::Mat log_kernel_2d;
    log_kernel.multiply(log_kernel.t(), log_kernel_2d);
    cv::Mat laplacian_kernel = (cv::Mat_<float>(3, 3) <<
        0, 1, 0,
        1, -4, 1,
        0, 1, 0);
    cv::filter2D(log_kernel_2d, log_kernel_2d, -1, laplacian_kernel);

    // 对图像应用LoG核
    cv::Mat dst;
    cv::filter2D(src, dst, CV_32F, log_kernel_2d);

    // 将结果转换为8位图像以便于显示
    cv::Mat abs_dst;
    cv::convertScaleAbs(dst, abs_dst);

    // 显示原始图像和LoG边缘检测的结果
    cv::namedWindow("Original Image", cv::WINDOW_AUTOSIZE);
    cv::imshow("Original Image", src);

    cv::namedWindow("LoG Edge Detection", cv::WINDOW_AUTOSIZE);
    cv::imshow("LoG Edge Detection", abs_dst);

    cv::waitKey();

    return 0;
}
在这个示例中,我们首先构建了一个离散的LoG核,并使用该核对图像进行卷积操作。这样可以直接得到LoG边缘检测的结果。注意,实际应用中可能需要进一步调整高斯核的尺寸和标准差,以适应不同的图像和场景。
在OpenCV中,cv::Mat 类确实没有名为 multiply 的成员函数。你可能是想实现一个矩阵与其转置的乘积,但这应该通过其他方式来完成。cv::Mat 类有一个 mulTransposed 方法,但它并不适用于你的情况,因为你实际上是想做外积(即矩阵与其转置的乘积)。你可以使用点乘(Hadamard乘积)或者直接构造一个二维高斯核并应用Laplacian算子来构建LoG核。以下是修正后的代码:#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

cv::Mat createLogKernel(int kernel_size, double sigma) {
    // 获取一维高斯核
    cv::Mat kernel1D = getGaussianKernel(kernel_size, sigma, CV_32F);

    // 通过点乘来构建二维高斯核
    cv::Mat kernel2D = Mat::zeros(kernel_size, kernel_size, CV_32F);
    for (int i = 0; i < kernel_size; ++i) {
        for (int j = 0; j < kernel_size; ++j) {
            kernel2D.at<float>(i, j) = kernel1D.at<float>(i) * kernel1D.at<float>(j);
        }
    }

    // 构建Laplacian核
    cv::Mat laplacian_kernel = (cv::Mat_<float>(3, 3) <<
        0, 1, 0,
        1, -4, 1,
        0, 1, 0);

    // 将二维高斯核与Laplacian核相乘
    cv::Mat logKernel = Mat::zeros(kernel_size, kernel_size, CV_32F);
    for (int i = 0; i < kernel_size; ++i) {
        for (int j = 0; j < kernel_size; ++j) {
            logKernel.at<float>(i, j) = kernel2D.at<float>(i, j) * laplacian_kernel.at<float>((i % 3), (j % 3));
        }
    }

    return logKernel;
}

int main(int argc, char** argv) {
    int kernel_size = 5;
    double sigma = 1.4;

    cv::Mat logKernel = createLogKernel(kernel_size, sigma);

    // 输出LoG核
    cout << "LoG Kernel:\n" << logKernel << endl;

    return 0;
}
代码解释1. 获取一维高斯核:使用 getGaussianKernel 函数获得一维高斯核。2. 构建二维高斯核:通过将一维高斯核的每一个元素与其他所有元素相乘来构建二维高斯核。3. 构建Laplacian核:定义一个3x3的Laplacian核。4. 构建LoG核:通过将二维高斯核与Laplacian核相乘来构建LoG核。注意事项•外积:这里的二维高斯核是通过一维高斯核的外积来实现的,即每个元素与另一个向量中的每个元素相乘。•Laplacian核:Laplacian核是一个固定的3x3核,它用于计算二阶导数。•LoG核:通过将二维高斯核与Laplacian核相乘来构建LoG核。如果你只需要构建一个LoG核而不关心具体实现细节,可以直接使用OpenCV的 filter2D 函数结合 getGaussianKernel 和 Laplacian 算子来实现:#include <opencv2/opencv.hpp>

using namespace cv;

cv::Mat createLogKernel(int kernel_size, double sigma) {
    // 获取一维高斯核
    cv::Mat kernel1D = getGaussianKernel(kernel_size, sigma, CV_32F);

    // 构建二维高斯核
    cv::Mat kernel2D = kernel1D * kernel1D.t();

    // 应用Laplacian算子
    cv::Mat laplacianKernel = (cv::Mat_<float>(3, 3) <<
        0, 1, 0,
        1, -4, 1,
        0, 1, 0);

    cv::Mat logKernel;
    cv::filter2D(kernel2D, logKernel, -1, laplacianKernel);

    return logKernel;
}
这种方式更加简洁,但也需要保证 kernel_size 至少为3,否则 filter2D 可能会失败。
#include <opencv2/opencv.hpp>
#include <iostream>

int main(int argc, char** argv)
{
	/*if (argc != 2) {
		std::cout << "Usage: " << argv[0] << " <Image Path>" << std::endl;
		return -1;
	}*/

	// 读取图像
	cv::Mat src = cv::imread("07.jpg", cv::IMREAD_GRAYSCALE);

	if (!src.data) {
		std::cout << "Error: Image cannot be loaded!" << std::endl;
		return -1;
	}

	// 定义高斯核的尺寸和标准差
	int kernel_size = 5; // 一般选择奇数
	double sigma = 1.4; // 高斯核的标准差

	// 构建LoG核
	//cv::Mat log_kernel = cv::getGaussianKernel(kernel_size, sigma, CV_32F);
	//cv::Mat log_kernel_2d;
	//log_kernel.multiply(log_kernel.t(), log_kernel_2d);
	//cv::Mat laplacian_kernel = (cv::Mat_<float>(3, 3) <<
	//	0, 1, 0,
	//	1, -4, 1,
	//	0, 1, 0);
	//cv::filter2D(log_kernel_2d, log_kernel_2d, -1, laplacian_kernel);

	// 获取一维高斯核
	// cv::Mat kernel1D = getGaussianKernel(kernel_size, sigma, CV_32F);
	cv::Mat log_kernel = cv::getGaussianKernel(kernel_size, sigma, CV_32F);
	// 构建二维高斯核
	//cv::Mat kernel2D = log_kernel * log_kernel.t();
	cv::Mat log_kernel_2d = log_kernel * log_kernel.t();
	// 应用Laplacian算子
	cv::Mat laplacian_kernel = (cv::Mat_<float>(3, 3) <<
		0, 1, 0,
		1, -4, 1,
		0, 1, 0);

	// cv::Mat logKernel;  
	// cv::filter2D(log_kernel_2d, logKernel, -1, laplacian_kernel);
	cv::filter2D(log_kernel_2d, log_kernel_2d, -1, laplacian_kernel);



	// 对图像应用LoG核
	cv::Mat dst;
	cv::filter2D(src, dst, CV_32F, log_kernel_2d);

	// 将结果转换为8位图像以便于显示
	cv::Mat abs_dst;
	cv::convertScaleAbs(dst, abs_dst);

	// 显示原始图像和LoG边缘检测的结果
	cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
	cv::imshow("Original Image", src);

	cv::namedWindow("LoG Edge Detection", cv::WINDOW_NORMAL);
	cv::imshow("LoG Edge Detection", abs_dst);

	cv::waitKey();

	return 0;
}

运行结果1

好像有错误!

示例代码2

以下是一个使用OpenCV C++实现LoG边缘检测的示例:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

void detectEdgesWithLog(const Mat &src, Mat &dst, double sigma) {
	// 首先应用高斯滤波器
	Mat blurred;
	GaussianBlur(src, blurred, Size(0, 0), sigma);

	// 应用Laplacian算子
	Mat laplacian;
	Laplacian(blurred, laplacian, CV_16S);

	// 将结果转换为8位无符号整数
	convertScaleAbs(laplacian, dst);
}

int main(int argc, char** argv) {

	// 加载图像
	Mat img = imread("08.png", IMREAD_GRAYSCALE);
	if (!img.data) {
		cout << "Error opening image" << endl;
		return -1;
	}

	// 设置高斯核的标准差
	double sigma = 1.4;

	// 检测边缘
	Mat edges;
	detectEdgesWithLog(img, edges, sigma);

	// 显示结果
	namedWindow("Original Image", WINDOW_NORMAL);
	imshow("Original Image", img);
	namedWindow("LoG Edges", WINDOW_NORMAL);
	imshow("LoG Edges", edges);

	waitKey(0);
	destroyAllWindows();

	return 0;
}



代码解释
1. 加载图像: 使用 imread 函数以灰度模式加载图像。
2. 高斯滤波: 使用 GaussianBlur 函数对图像进行高斯滤波处理,以去除噪声。
3. Laplacian算子: 使用 Laplacian 函数计算图像的Laplacian梯度。
4. 转换数据类型: 使用 convertScaleAbs 函数将16位有符号整数转换为8位无符号整数,以便于显示。
5. 显示结果: 使用 imshow 函数显示原始图像和LoG边缘检测的结果。

注意事项
•选择合适的高斯核大小: 在实际应用中,高斯核的大小和标准差(sigma)的选择会影响最终的边缘检测效果。较大的sigma值会检测到更大范围内的边缘,而较小的sigma值则会检测到更多的细节。
•参数调整: 可以尝试调整高斯核的标准差sigma来观察不同的边缘检测效果。
•性能考虑: LoG算子由于需要进行两次卷积操作(一次高斯滤波,一次Laplacian),因此计算量相对较大。在处理大尺寸图像时,可能会有一定的延迟。

运行结果2

示例代码3

#include <opencv2/opencv.hpp>
#include <iostream>

int main(int argc, char** argv)
{
	/*if (argc != 2) {
		std::cout << "Usage: " << argv[0] << " <Image Path>" << std::endl;
		return -1;
	}*/

	// 读取图像
	cv::Mat src = cv::imread("09.png", cv::IMREAD_GRAYSCALE);

	if (!src.data) {
		std::cout << "Error: Image cannot be loaded!" << std::endl;
		return -1;
	}

	// 定义高斯核的尺寸和标准差
	int kernel_size = 5; // 一般选择奇数
	double sigma = 1.4; // 高斯核的标准差

	// 使用高斯核进行平滑处理
	cv::Mat blurred;
	cv::GaussianBlur(src, blurred, cv::Size(kernel_size, kernel_size), sigma);

	// 使用Laplacian算子进行边缘检测
	cv::Mat dst;
	cv::Laplacian(blurred, dst, CV_16S, 3); // 使用3x3的内核

	// 将结果转换为8位图像以便于显示
	cv::Mat abs_dst;
	cv::convertScaleAbs(dst, abs_dst);

	// 显示原始图像和LoG边缘检测的结果
	cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
	cv::imshow("Original Image", src);

	cv::namedWindow("LoG Edge Detection", cv::WINDOW_NORMAL);
	cv::imshow("LoG Edge Detection", abs_dst);

	cv::waitKey();

	return 0;
}

解释
1.读取图像:从命令行参数读取图像路径,并将其加载为灰度图像。
2.高斯模糊:使用cv::GaussianBlur函数对图像进行高斯模糊处理,目的是减少图像中的噪声。这里定义了高斯核的尺寸和标准差。
3.拉普拉斯算子:对模糊后的图像应用拉普拉斯算子,使用cv::Laplacian函数。这里选择了一个3x3的内核大小。
4.转换为8位图像:因为拉普拉斯算子的结果可能是负值,我们需要将其转换为8位无符号整型图像以便于显示。使用cv::convertScaleAbs函数可以完成这个转换。
5.显示结果:使用cv::imshow函数分别显示原始图像和LoG边缘检测的结果。

参数调整
kernel_size:高斯核的尺寸,一般选择奇数,较大的尺寸会使得平滑效果更好,但也可能导致边缘变得模糊。
sigma:高斯核的标准差,决定了平滑的程度。较小的sigma值会保留更多的细节,但可能会引入更多的噪声;较大的sigma值会使图像更平滑,但可能会丢失一些细节。

运行结果3

实验代码4

 

#include "pch.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/highgui/highgui_c.h>
using namespace cv;
using namespace std;
//#pragma comment(lib,"opencv_world450d.lib")

 
//x,y方向联合实现获取高斯模板
void generateGaussMask(cv::Mat& Mask, cv::Size wsize, double sigma) 
{
	Mask.create(wsize, CV_64F);
	int h = wsize.height;
	int w = wsize.width;
	int center_h = (h - 1) / 2;
	int center_w = (w - 1) / 2;
	double sum = 0.0;
	double x, y;
	for (int i = 0; i < h; ++i) {
		y = pow(i - center_h, 2);
		for (int j = 0; j < w; ++j) {
			x = pow(j - center_w, 2);
			//因为最后都要归一化的,常数部分可以不计算,也减少了运算量
			double g = exp(-(x + y) / (2 * sigma*sigma));
			Mask.at<double>(i, j) = g;
			sum += g;
		}
	}
	Mask = Mask / sum;
}


//按二维高斯函数实现高斯滤波
///
void GaussianFilter(cv::Mat& src, cv::Mat& dst, cv::Mat window) 
{
	int hh = (window.rows - 1) / 2;
	int hw = (window.cols - 1) / 2;
	dst = cv::Mat::zeros(src.size(), src.type());
	//边界填充
	cv::Mat Newsrc;
	cv::copyMakeBorder(src, Newsrc, hh, hh, hw, hw, cv::BORDER_REPLICATE);//边界复制

	//高斯滤波
	for (int i = hh; i < src.rows + hh; ++i) {
		for (int j = hw; j < src.cols + hw; ++j) {
			double sum[3] = { 0 };

			for (int r = -hh; r <= hh; ++r) {
				for (int c = -hw; c <= hw; ++c) {
					if (src.channels() == 1) {
						sum[0] = sum[0] + Newsrc.at<uchar>(i + r, j + c) * window.at<double>(r + hh, c + hw);
					}
					else if (src.channels() == 3) {
						cv::Vec3b rgb = Newsrc.at<cv::Vec3b>(i + r, j + c);
						sum[0] = sum[0] + rgb[0] * window.at<double>(r + hh, c + hw);//B
						sum[1] = sum[1] + rgb[1] * window.at<double>(r + hh, c + hw);//G
						sum[2] = sum[2] + rgb[2] * window.at<double>(r + hh, c + hw);//R
					}
				}
			}

			for (int k = 0; k < src.channels(); ++k) {
				if (sum[k] < 0)
					sum[k] = 0;
				else if (sum[k] > 255)
					sum[k] = 255;
			}
			if (src.channels() == 1)
			{
				dst.at<uchar>(i - hh, j - hw) = static_cast<uchar>(sum[0]);
			}
			else if (src.channels() == 3)
			{
				cv::Vec3b rgb = { static_cast<uchar>(sum[0]), static_cast<uchar>(sum[1]), static_cast<uchar>(sum[2]) };
				dst.at<cv::Vec3b>(i - hh, j - hw) = rgb;
			}

		}
	}

}


//DOG高斯差分
///
void DOG1(cv::Mat &src, cv::Mat &dst, cv::Size wsize, double sigma, double k = 1.6) 
{
	cv::Mat Mask1, Mask2, gaussian_dst1, gaussian_dst2;
	generateGaussMask(Mask1, wsize, k*sigma);//获取二维高斯滤波模板1
	generateGaussMask(Mask2, wsize, sigma);//获取二维高斯滤波模板2

	//高斯滤波
	GaussianFilter(src, gaussian_dst1, Mask1);
	GaussianFilter(src, gaussian_dst2, Mask2);

	dst = gaussian_dst1 - gaussian_dst2 - 1;

	cv::threshold(dst, dst, 0, 255, cv::THRESH_BINARY);
}



//DOG高斯差分--使用opencv的GaussianBlur

void DOG2(cv::Mat &src, cv::Mat &dst, cv::Size wsize, double sigma, double k = 1.6) 
{
	cv::Mat gaussian_dst1, gaussian_dst2;
	//高斯滤波
	cv::GaussianBlur(src, gaussian_dst1, wsize, k*sigma);
	cv::GaussianBlur(src, gaussian_dst2, wsize, sigma);

	dst = gaussian_dst1 - gaussian_dst2;
	cv::threshold(dst, dst, 0, 255, cv::THRESH_BINARY);
}

int main() 
{
	cv::Mat src = cv::imread("jo.png");
	if (src.empty()) {
		return -1;
	}
	if (src.channels() > 1) cv::cvtColor(src, src, CV_RGB2GRAY);
	cv::Mat edge1, edge2;
	DOG1(src, edge1, cv::Size(7, 7), 2);
	DOG2(src, edge2, cv::Size(7, 7), 2);
	cv::namedWindow("src", CV_WINDOW_NORMAL);
	imshow("src", src);
	cv::namedWindow("My_DOG", CV_WINDOW_NORMAL);
	imshow("My_DOG", edge1);

	cv::namedWindow("Opencv_DOG", CV_WINDOW_NORMAL);
	imshow("Opencv_DOG", edge2);
	cv::waitKey(0);
	return 0;
}

运行结果4

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

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

相关文章

MPICH 源码编译 with ucx with cuda,应用示例

先基于 cuda 编译ucx 再基于 ucx 编译 mpich mkdir mpich mkdir ucx 1, 安装 ucx 预备环境&#xff1a; sudo apt-get install valgrind sudo apt-get install libibverbs-dev librdmacm-dev 下载ucx 源代码 git clone --recursive https://github.com/openucx/ucx.git cd…

堆排序,快速排序

目录 1.堆排序 2.快速排序 1.hoare版本 2.挖坑法 3.前后指针法 注意点 1.堆排序 void Swap(int* a, int* b) {int tmp *a;*a *b;*b tmp; } void adjustdown(int* a, int n, int parent) {int child parent * 2 1;while (child < n){if (child 1 < n &&am…

【Python基础】Python lambda(简洁与高效的匿名函数)

本文收录于 《Python编程入门》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程基础知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、lambda函数的基本概念三、lambda函数的应用实例3.1 在列表排序中使用lambda函数3.2 在map()函数中…

(批处理)设置延时+设置关机倒计时

使用方式&#xff1a;建立一个文本文件夹&#xff0c;将文件扩展名改为.bat&#xff0c;右键单击后编辑&#xff0c;将代码复制进去。 将文件保存 echo off echo 三秒后会出现一个提示自动关机ping -n 3 127.0.0.1 >nul rem 实现的功能是在这里停3秒再继续往下执行 rem 以…

OpenCore Legacy Patcher 2.0.0 发布,83 款不受支持的 Mac 机型将能运行最新的 macOS Sequoia

在不受支持的 Mac 上安装 macOS Sequoia (OpenCore Legacy Patcher v2.0.0) Install macOS on unsupported Macs 请访问原文链接&#xff1a;https://sysin.org/blog/install-macos-on-unsupported-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主…

【Linux】多路转接epoll

一、I/O多路转接 poll 1.1 poll函数接口 函数原型 函数参数 fds&#xff1a;是一个poll函数监听的结构列表&#xff0c;每一个元素中包含了三部分内容&#xff1a;文件描述符&#xff0c;监听的事件集合&#xff0c;返回的事件集合。nfds&#xff1a;表示的是fds数组的长度tim…

VUE + NODE 历史版本安装

以node 12.20.0为例子&#xff0c;想下载哪个版本&#xff0c;后面写哪个版本 https://registry.npmmirror.com/binary.html?pathnode/v12.20.0/ 安装国内镜像7.1.0 cnpm npm install -g cnpm7.1.0 -g --registryhttps://registry.npmmirror.com 安装vue脚手架4.5.15 cnpm …

【有啥问啥】深入浅出马尔可夫链蒙特卡罗(Markov Chain Monte Carlo, MCMC)算法

深入浅出马尔可夫链蒙特卡罗&#xff08;Markov Chain Monte Carlo, MCMC&#xff09;算法 0. 引言 Markov Chain Monte Carlo&#xff08;MCMC&#xff09;是一类用于从复杂分布中采样的强大算法&#xff0c;特别是在难以直接计算分布的情况下。它广泛应用于统计学、机器学习…

【linux基础】linux中的开发工具(4)--调试器gdb的使用

目录 前言一&#xff0c;背景二&#xff0c;gdb的使用1. 启动 gdb 调试器&#xff1a;2. 罗列代码信息3. 运行程序4. 有关断点的操作(1) 打断点(2) 查看断点(3) 删除断点(4) 在一次调试中&#xff0c;断点是递增的(5) 关闭断点(6) 开启断点(7) 逐过程调试&#xff0c;相当于 F1…

我与Linux的爱恋:进程|进程的查看与管理|创建进程

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;Linux的学习 ​ 文章目录 一、进程的概念1.什么是进程2.在这里插入代码片多进程管理3.描述进程-PCB 2.查看进程与管理进程1.使用指令查看进程2.通过系统调用函数查看pid3.杀进程4.ppid&…

如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?

优质博文&#xff1a;IT-BLOG-CN 问题 我在 macOS 中使用 vscode 版本 1.92.2&#xff0c;并安装了Java 扩展包v0.29.0。当我打开command click或right click->Go to definition一个没有源代码的类时&#xff0c;vscode 会使用 FernFlower 反编译器打开 .class 文件。但…

一步一步自制py脚本并且并且修改为exe可执行文件教学外附带SHA-1解密exe文件资源

第一步&#xff1a;安装 Python 下载 Python&#xff1a;访问 Python 官网 下载并安装最新版本的 Python。安装时选择添加到环境变量 PATH&#xff1a;在安装过程中&#xff0c;确保勾选“Add Python to PATH”选项。 第二步&#xff1a;编写 Python 脚本 创建一个新的 Pyth…

HTB-Base(strcmp函数绕过、sudo -l提权)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解Base靶场&#xff0c;起点内容到此完结 渗透过程 信息搜集 服务器开放了22SSH服务 和 80HTTP服务 目录爆破 通过目录扫描出/login 和/asserts文件夹 发现/login 拥有目录遍历漏洞login.php.swp 是使用…

Mysql_使用简介

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

循环练习 案例

swich新特性 jdk12 穿透 逢七过 //含有七和被七整除舍去 public class test1 {public static void main(String[] args){for (int i 1; i <100 ; i) {if(i%70||i%107||i/107){continue;}System.out.println(i);}} } 求平方根 //输入大于2的整数&#xff0c;求平方根&…

AI基础 L22 Uncertainty over Time I 时间的不确定性

Time and Uncertainty 1 Time and Uncertainty States and Observations • discrete-time models: we view the world as a series of snapshots or time slices • the time interval ∆ between slices, we assume to be the same for every interval • Xt: denotes the se…

C++编译环境(IDE)推荐及安装

IDE是什么 嗨嗨嗨&#xff0c;我又来水博文了 今天来给大家推荐几款好用的IDE IDE是集成开发环境&#xff08;Integrated Development Environment&#xff09;的缩写&#xff0c;是一种软件应用程序&#xff0c;提供了用于软件开发的各种工具和功能&#xff0c;包括代码编辑…

windows C++ 并行编程-PPL 中的取消操作(一)

并行模式库 (PPL) 中取消操作的角色、如何取消并行工作以及如何确定取消并行工作的时间。 运行时使用异常处理实现取消操作。 请勿在代码中捕捉或处理这些异常。 此外&#xff0c;还建议你在任务的函数体中编写异常安全的代码。 例如&#xff0c;可以使用获取资源即初始化 (RA…

LidarView之定制版本号

介绍 LidarView软件需要关注2个版本号&#xff1a;1.Application版本号&#xff1b;2.安装包版本号 Application版本号 改变LV_VERSION_FULL可达到改变软件版本号的目的 SET(LV_VERSION_FULL "V1.3.0")标题栏版本号 关于对话框 安装包版本号 在Inno Setup Compi…

【退役之再次线上部署】Spring Boot + VUE + Nginx + MySQL

这篇博客写在凌晨 4 点 20 分&#xff0c;这个时候我刚线上部署完成 web 项目&#xff0c;自己写的全栈项目 这个点儿&#xff0c;也睡不着了&#xff0c;索性就写篇博客记录一下 一、踩坑实录 这个是 最重要的&#xff0c;所以写在前面 Nginx 配置文件 location location /a…