当前位置: 首页 > news >正文

Opencv-C++笔记 (15) : 像素重映射 与 图像扭曲

文章目录

  • 一、重映射简介
  • 二、图像扭曲

一、重映射简介

重映射,就是把一幅图像中某位置的像素放置到另一图像指定位置的过程。即:
在这里插入图片描述
在重映射过程中,图像的大小也可以同时发生改变。此时像素与像素之间的关系就不是一一对应关系,因此在重映射过程中,可能会涉及到像素值的插值计算。

Remap(
InputArray src,       输入图像(灰度图或真彩图均可)
OutputArray dst,       输出图像(要求大小和xmap,ymap相同,通道数目及数据类型和src相同)
InputArray map1,      x 映射表 CV_32FC1/CV_32FC2
InputArray map2,      y 映射表
int interpolation,       选择的插值方法,常见线性插值,可选择立方等
int borderMode,       BORDER_CONSTANT
const Scalar borderValue   color
)

头文件 quick_opencv.h:声明类与公共函数

#pragma once
#include <opencv2\opencv.hpp>
using namespace cv;class QuickDemo {
public:...void remap_Demo(Mat& image1);void MLS(Mat& src, std::vector<Point> p, std::vector<Point> q);void MLS(Mat& src, int* p, int* q, int rows, int cols);
};

主函数调用该类的公共成员函数

#include <opencv2\opencv.hpp>
#include <quick_opencv.h>
#include <iostream>
using namespace cv;int main(int argc, char** argv) {Mat src = imread("D:\\Desktop\\pandas_small22.png");if (src.empty()) {printf("Could not load images...\n");return -1;}QuickDemo qk;qk.remap_Demo(src);vector<Point> p{Point(30, 147), Point(147, 147), Point(268, 147), Point(112, 148),Point(186, 148), Point(98, 316), Point(211, 316)};vector<Point> q{ Point(28, 209), Point(126, 143), Point(282, 26), Point(71, 236), Point(136, 240), Point(79, 313), Point(190, 310)};qk.MLS(src1, p, q);int p_array[7][2] = { {30, 147}, {147, 147}, {268, 147}, {112, 148}, {186, 148}, {98, 316}, {211, 316} };int q_array[7][2] = { {28, 209}, {126, 143}, {282, 26},  {71, 236},  {136, 240}, {79, 313}, {190, 310} };qk.MLS(src1, (int *)p_array, (int*)q_array, 7, 2);waitKey(0);destroyAllWindows();return 0;
}

源文件 quick_demo.cpp:实现类与公共函数

void update_map(Mat& image, int index, Mat& x_map, Mat& y_map) {int height = image.rows;int width = image.cols;double h_41 = height * 0.25;double h_43 = height * 0.75;double w_41 = width * 0.25;double w_43 = width * 0.75;for (int h = 0; h < height; h++) {float* x_ptr = x_map.ptr<float>(h);float* y_ptr = y_map.ptr<float>(h);for (int w = 0; w < width; w++) {switch (index){case 0:if (h > h_41 && h < h_43 && w>w_41 && w < w_43) {*x_ptr++ = 2 * (w - w_41 + 0.5);*y_ptr++ = 2 * (h - h_41 + 0.5);}else{*x_ptr++ = 0;*y_ptr++ = 0;}break;case 1:*x_ptr++ = width - w - 1;*y_ptr++ = h;break;case 2:*x_ptr++ = w;*y_ptr++ = height - h - 1;break;case 3:*x_ptr++ = width - w - 1;*y_ptr++ = height - h - 1;break;}}}}
void QuickDemo::remap_Demo(Mat& image) {Mat dst, x_map, y_map;int index = 0;x_map.create(image.size(), CV_32FC1);y_map.create(image.size(), CV_32FC1);int c = 0;while (true){c = waitKey(400);if ((char)c==27){break;}index = c % 4;update_map(image,index, x_map, y_map);remap(image, dst, x_map, y_map, INTER_LINEAR, BORDER_CONSTANT, Scalar(255, 0, 0));imshow("remap", dst);}
}

如上两个函数,update_map,用于更新remap的具体映射方法,remap_Demo为调用函数。
在这里插入图片描述

二、图像扭曲

MLS算法 图像扭曲 Image Deformation Using Moving Least Squares 论文。
最小二乘法(MLS)对图像进行变形 python 实现
在这里插入图片描述
在这里插入图片描述

Point NewPoint(Point V, vector<Point> p, vector<Point> q){vector<float>W;Point p_star, q_star = Point(0, 0);for (int i = 0; i <= p.size() - 1; i++){float temp;if (p[i] == V){temp = INT_MAX;}else{temp = 1.0 / (((p[i].x - V.x) * (p[i].x - V.x)) + ((p[i].y - V.y) * (p[i].y - V.y)));}W.push_back(temp);}float px = 0, py = 0, qx = 0, qy = 0, W_sum = 0;for (int i = 0; i <= W.size() - 1; i++){px += W[i] * p[i].x;py += W[i] * p[i].y;qx += W[i] * q[i].x;qy += W[i] * q[i].y;W_sum += W[i];}p_star.x = px / W_sum;p_star.y = py / W_sum;q_star.x = qx / W_sum;q_star.y = qy / W_sum;vector<Point> p_hat, q_hat;for (int i = 0; i <= p.size() - 1; i++){p_hat.push_back(p[i] - p_star);q_hat.push_back(q[i] - q_star);}Mat pi_hat_t_ = Mat::zeros(2, 1, CV_32FC1);Mat_<float> pi_hat_t = pi_hat_t_;Mat pi_hat_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> pi_hat = pi_hat_;Mat M_1_ = Mat::zeros(2, 2, CV_32FC1);Mat_<float> M_1 = M_1_;for (int i = 0; i <= p_hat.size() - 1; i++){pi_hat_t.at<float>(0, 0) = p_hat[i].x;pi_hat_t.at<float>(1, 0) = p_hat[i].y;pi_hat.at<float>(0, 0) = p_hat[i].x;pi_hat.at<float>(0, 1) = p_hat[i].y;M_1 += pi_hat_t * W[i] * pi_hat;}Mat_<float> M_1_inv = M_1.inv();M_1 = M_1_inv;Mat pj_hat_t_ = Mat::zeros(2, 1, CV_32FC1);Mat_<float> pj_hat_t = pj_hat_t_;Mat qj_hat_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> qj_hat = qj_hat_;Mat M_2_ = Mat::zeros(2, 2, CV_32FC1);Mat_<float> M_2 = M_2_;for (int j = 0; j <= q.size() - 1; j++){pj_hat_t.at<float>(0, 0) = p_hat[j].x;pj_hat_t.at<float>(1, 0) = p_hat[j].y;qj_hat.at<float>(0, 0) = q_hat[j].x;qj_hat.at<float>(0, 1) = q_hat[j].y;M_2 += W[j] * pj_hat_t * qj_hat;}Mat_<float> M = M_1 * M_2;//ok//cout << "M = " << M << endl;Point x_p_star = V - p_star;Mat M_x_p_star_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> M_x_p_star = M_x_p_star_;M_x_p_star.at<float>(0, 0) = x_p_star.x;M_x_p_star.at<float>(0, 1) = x_p_star.y;Mat M_q_star_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> M_q_star = M_q_star_;M_q_star.at<float>(0, 0) = q_star.x;M_q_star.at<float>(0, 1) = q_star.y;Mat_<float> Lv = M_x_p_star * M + M_q_star;return Point(Lv.at<float>(0, 0), Lv.at<float>(0, 1));
}void QuickDemo::MLS(Mat& src, std::vector<Point> p, std::vector<Point> q){double time0 = static_cast<double>(getTickCount());Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){Point old = Point(j, i);Point new_point = NewPoint(old, p, q);//cout << "old = " << old << "\tnew  = " << new_point << endl;dst.at<Vec3b>(i, j) = src.at<Vec3b>(abs(new_point.y), abs(new_point.x));}}double time1 = static_cast<double>(getTickCount());cout << "Total cost time is " << ((time1 - time0) / getTickFrequency()) << "seconds" << endl;imshow("dst_msl", dst);
}

重载函数

Point NewPoint(Point V, float* W, int* p, int* q , float* p_hat, float* q_hat, int rows, int cols) {Point p_star, q_star = Point(0, 0);float temp = 0;float px = 0, py = 0, qx = 0, qy = 0, W_sum = 0;for (int i = 0; i < rows; i++) {int p_0 = *(p + i * cols);int p_1 = *(p + i * cols + 1);if (!(p_0 == V.x && p_1 == V.y)) {temp = 1.0 / (((p_0 - V.x) * (p_0 - V.x)) + ((p_1 - V.y) * (p_1 - V.y)));}else {temp = INT_MAX;}W[i] = temp;px += temp * p_0;py += temp * p_1;qx += temp * (*(q + i * cols));qy += temp * (*(q + i * cols + 1));W_sum += temp;}p_star.x = px / W_sum;p_star.y = py / W_sum;q_star.x = qx / W_sum;q_star.y = qy / W_sum;for (int i = 0; i < rows; i++) {*(p_hat + i * cols) = *(p + i * cols) - p_star.x;*(p_hat + i * cols + 1) = *(p + i * cols + 1) - p_star.y;*(q_hat + i * cols) = *(q + i * cols) - p_star.x;*(q_hat + i * cols + 1) = *(q + i * cols + 1) - p_star.y;}// ====================================Mat pi_hat_t_ = Mat::zeros(2, 1, CV_32FC1);Mat_<float> pi_hat_t = pi_hat_t_;Mat pi_hat_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> pi_hat = pi_hat_;Mat M_1_ = Mat::zeros(2, 2, CV_32FC1);Mat_<float> M_1 = M_1_;// ====================================Mat pj_hat_t_ = Mat::zeros(2, 1, CV_32FC1);Mat_<float> pj_hat_t = pj_hat_t_;Mat qj_hat_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> qj_hat = qj_hat_;Mat M_2_ = Mat::zeros(2, 2, CV_32FC1);Mat_<float> M_2 = M_2_;// ====================================for (int i = 0; i < rows; i++) {float p_hat_x = *(p_hat + i * cols);float p_hat_y = *(p_hat + i * cols + 1);pi_hat_t.at<float>(0, 0) = p_hat_x;pi_hat_t.at<float>(1, 0) = p_hat_y;pi_hat.at<float>(0, 0) = p_hat_x;pi_hat.at<float>(0, 1) = p_hat_y;M_1 += pi_hat_t * W[i] * pi_hat;pj_hat_t.at<float>(0, 0) = p_hat_x;pj_hat_t.at<float>(1, 0) = p_hat_y;qj_hat.at<float>(0, 0) = *(q_hat + i * cols);qj_hat.at<float>(0, 1) = *(q_hat + i * cols + 1);M_2 += pj_hat_t * W[i] * qj_hat;}Mat_<float> M_1_inv = M_1.inv();M_1 = M_1_inv;Mat_<float> M = M_1 * M_2;//=====================================//// 	  如下为总公式计算////======================================Point x_p_star = V - p_star;Mat M_x_p_star_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> M_x_p_star = M_x_p_star_;M_x_p_star.at<float>(0, 0) = x_p_star.x;M_x_p_star.at<float>(0, 1) = x_p_star.y;Mat M_q_star_ = Mat::zeros(1, 2, CV_32FC1);Mat_<float> M_q_star = M_q_star_;M_q_star.at<float>(0, 0) = q_star.x;M_q_star.at<float>(0, 1) = q_star.y;Mat_<float> Lv = M_x_p_star * M + M_q_star;return Point(Lv.at<float>(0, 0), Lv.at<float>(0, 1));}void QuickDemo::MLS(Mat& src, int* p, int* q, int rows, int cols) {double time0 = static_cast<double>(getTickCount());Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC3);assert(7 == rows);               // 若断言失败请修改如下三个数组的长度为rowsfloat W[7] = { 0 };              // 权重长度为p数组长度:rows=7float p_hat[7][2] = { 0 };       // p_hat长度为p数组长度:rows=7float q_hat[7][2] = { 0 };       // q_hat长度为p数组长度:rows=7for (int i = 0; i < src.rows; i++) {for (int j = 0; j < src.cols; j++) {Point new_point = NewPoint(Point(j, i), W, p, q, (float*)p_hat, (float*)p_hat, rows, cols);//cout << "old = " << old << "\tnew  = " << new_point << endl;dst.at<Vec3b>(i, j) = src.at<Vec3b>(abs(new_point.y), abs(new_point.x));//cout << "src.at<uchar> = " << src.at<Vec3b>(new_point.y,new_point.x) << endl;}}double time1 = static_cast<double>(getTickCount());cout << "Total cost time is " << ((time1 - time0) / getTickFrequency()) << "seconds" << endl;imshow("dst_msl", dst);
}
————

在这里插入图片描述
鸣谢与拓展阅读:
使用范例 记录四图像处理之瘦脸 MLS算法 C++实现
OpenCV局部变形算法探究添加链接描述
基于移动最小二乘(MLS)的图像扭曲刚性变形python实现
使用重映射实现图像的局部扭曲 来实现 图像增强。

相关文章:

Opencv-C++笔记 (15) : 像素重映射 与 图像扭曲

文章目录 一、重映射简介二、图像扭曲 一、重映射简介 重映射&#xff0c;就是把一幅图像中某位置的像素放置到另一图像指定位置的过程。即&#xff1a; 在重映射过程中&#xff0c;图像的大小也可以同时发生改变。此时像素与像素之间的关系就不是一一对应关系&#xff0c;因…...

【Java】UWB高精度工业人员安全定位系统源码

基于VueSpring boot前后端分离架构开发的一套UWB技术高精度定位系统源码。 UWB高精度人员定位系统提供实时定位、电子围栏、轨迹回放等基础功能以及各种拓展功能,用户可根据实际需要任意选择搭配拓展功能。该系统简易部署&#xff0c;方便使用&#xff0c;实时响应。UWB高精度定…...

文本NLP噪音预处理(加拼写检查)

最近总结修改了下预处理方法&#xff0c;记录下 首先download需要的依赖 pip install pyenchantpip install nltk pyenchant 是用来检测拼写正确的&#xff0c;如果你的文本里面可能包含非正确拼写的单词&#xff0c;那就忽略它&#xff0c;nltk用来做分词的。 python -m nlt…...

[Docker实现测试部署CI/CD----自由风格的CI操作[最终架构](5)]

目录 11、自由风格的CI操作&#xff08;最终&#xff09;Jenkins容器化实现方案修改 docker.sock 权限修改 Jenkins 启动命令后重启 Jenkins构建镜像推送到Harbor修改 daemon.json 文件Jenkins 删除构建后操作Jenkins 添加 shell 命令重新构建 Jenkins通知目标服务器拉取镜像目…...

纯JS+Vue实现一个仪表盘

在使用canvas的时候发现数值变化&#xff0c;每次都要重新渲染&#xff0c;值都从0开始&#xff0c;这和我的需求冲突。 1. 先绘制基本的圆环背景&#xff0c;利用border-color和border-radius将正方形变成基本的圆环。 <div class"circle"><div class&qu…...

标定(内参、外参)

在计算机视觉中&#xff0c;特别是在相机标定和立体视觉领域&#xff0c;内参&#xff08;intrinsic parameters&#xff09;和外参&#xff08;extrinsic parameters&#xff09;是非常重要的概念。它们与相机的几何属性和姿态有关。 内参&#xff08;Intrinsic Parameters&am…...

基于ffmpeg与SDL的视频播放库

由于工作需要&#xff0c;自己封装的基于ffmpeg的视频编解码库&#xff0c;显示采用了SDL库。可以播放本地文件或网络流&#xff0c;支持多端口播放&#xff0c;支持文字叠加&#xff0c;截图、视频录制等等。 头文件代码&#xff1a; #pragma once #ifdef __DLLEXPORT #defin…...

基于二进制草蝉优化算法选择特征并使用 KNN 进行训练(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 基于二进制草蝉优化算法选择特征并使用KNN&#xff08;K-Nearest Neighbors&#xff0c;K最近邻算法&#xff09;进行训练是一种…...

14-4_Qt 5.9 C++开发指南_QUdpSocket实现 UDP 通信_UDP组播

文章目录 1. UDP组播的特性2. UDP 组播实例程序的功能3. 组播功能的程序实现4. 源码4.1 可视化UI设计4.2 mainwindow.h4.3 mainwindow.cpp 1. UDP组播的特性 下图简单表示了组播的原理。UDP 组播是主机之间“一对一组”的通信模式&#xff0c;当多个客户端加入由一个组播地址定…...

ai图片合成软件帮你创造个性绚丽

嘿&#xff01;悄悄告诉你一个小秘密&#xff0c;现在有一款超酷的软件&#xff0c;它能让你的图片变得活灵活现&#xff0c;就像跳出了屏幕一样&#xff01;没错&#xff0c;这就是ai图片制作软件&#xff01;想象一下&#xff0c;你拍摄了一张美丽的风景照片&#xff0c;但总…...

git 版本回退

git 没有push之前&#xff0c;可以用git reset --mixed回退&#xff0c;就是把add 的内容和commit的内容都撤销 在push之后&#xff0c;你只有2种操作 1.git reset 退回到你想要的那个版本 有配置选项 如果是soft就是当前版本删掉&#xff0c;之前改的代码保留&#xff0c;ha…...

使用Jackson自定义序列化操作(Jackson – Custom Serializer)

目录 Standard Serialization of an Object GraphCustom Serializer on the ObjectMapperCustom Serializer on the Class Standard Serialization of an Object Graph Data NoArgsConstructor AllArgsConstructor public class Item {public int id;public String itemName;p…...

Python-元组

元组&#xff08;Tuples&#xff09;详解 在Python中&#xff0c;元组&#xff08;Tuples&#xff09;是一种有序的数据类型&#xff0c;它可以包含任意类型的元素&#xff0c;包括数字、字符串、列表等。与列表相似&#xff0c;元组也是用来存储一组数据&#xff0c;但与列表…...

快速转换PDF文件: Python和PyMuPDF教程

解决问题 有时候将文档上传Claude2做分析&#xff0c;有大小限制&#xff0c;所以需要切割pdf文档为几个小点的文档&#xff0c;故才有了本文章。 如何用Python和PyMuPDF制作你想要大小的PDF&#xff1f; PDF是一种广泛使用的文件格式&#xff0c;可以在任何设备上查看和打印…...

规划模型Matlab代码

文章目录 数学规划定义一般形式分类 1.线性规划(linear programming)2.非线性规划(nonlinear programming)3. 整数规划(integer programming)4. 0-1规划(0-1 programming)5. 最大最小化模型6. 多目标规划模型7.敏感性分析&#xff08;对权重&#xff09;[例题] 数学规划定义 数…...

用html+javascript打造公文一键排版系统11:改进单一附件说明排版

一、用htmljavascript打造公文一键排版系统10中的一个bug 在 用htmljavascript打造公文一键排版系统10&#xff1a;单一附件说明排版 中&#xff0c;我们对附件说明的排版函数是&#xff1a; function setAtttDescFmt(p) {var t p;var a ;if (-1 ! t.indexOf(:))//是半角冒…...

snap xxx has “install-snap“ change in progress

error description * 系重复安装&#xff0c;进程冲突 solution 展示snap的改变 然后sudo snap abort 22即可终止该进程 之后重新运行install command&#xff5e;&#xff5e; PS: ubuntu有时候加载不出来&#xff0c;执行resolvectl flush-caches&#xff0c;清除dns缓存…...

Elasticsearch 性能调优指南

目录 1、通用优化策略 1.1 通用最小化法则 1.2 职责单一原则 1.3 其他 2、写性能调优 2.1 基本原则 2.2 优化手段 2.2.1 增加 flush 时间间隔&#xff0c; 2.2.2 增加refresh_interval的参数值 2.2.3 增加Buffer大小&#xff0c; 2.2.4 关闭副本 2.2.5 禁用swap 2…...

学习Boost一:学习方法和学习目的

学习目的 Boost 的学习目的&#xff1a; 因为从知乎和CSND上根据了解内容来看&#xff0c;Boost作为一个历史悠久的开源库&#xff0c;已经脱离了一个单纯的库的概念了&#xff0c;他因庞大的涉及面应当被称之为库集。 并且&#xff0c;因为boost库优秀的试用反馈和开发人员的…...

c语言每日一练(1)

前言&#xff1a; 每日一练系列&#xff0c;每一期都包含5道选择题&#xff0c;2道编程题&#xff0c;博主会尽可能详细地进行讲解&#xff0c;令初学者也能听的清晰。每日一练系列会持续更新&#xff0c;暑假时三天之内必有一更&#xff0c;到了开学之后&#xff0c;将看学业情…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...