Python自动化(6)——图像模块

本文所述的方法都是基于前几章的后台点击,因此同样需要绑定窗口句柄。

Python自动化(6)——图像模块

识色

定点比色

def cv2CompareColorOneMatch(self, x, y, hexColor, _similar=0, border=None):startX = 0startY = 0similar = _similar + self.colorOffsetif border:startX = border[0]startY = border[1]color = self.Hex2RGB(hexColor)screenQImg = self.screen.captureScreen(None, border)if int(x)-startX <= 0:print('cv2CompareColorOneMatch error x: '+str(x)+', startX: '+str(startX))if int(y)-startY <= 0:print('cv2CompareColorOneMatch error y: '+str(y)+', startY: '+str(startY))res = QColor(screenQImg.pixel(int(x)-startX, int(y)-startY)).getRgb()print('cv2CompareColorOneMatch x: '+str(x)+', y: '+str(y)+', re: '+str(res))if abs(res[0] - color[0]) < similar and abs(res[1] - color[1]) < similar and abs(res[2] - color[2]) < similar:return Trueelse:return False

参数:
前两个传输是绑定的窗口的x,y坐标
hexColor:16进制的色值(传字符串,例如:“#fffbeb”)
_similar:色值偏移值,默认为0,一般会传3~5
border:截图范围,默认截全屏。截图截少一点,(理论上)性能好一点,使用时一般只会截那个点周围的十来个像素
返回值:如果截图判断的点与传进来的色值相减,RGB每个值都在色值偏移范围内,返回True,否则返回False
其中,self.Hex2RGB是将16进制色值转换为RGB值的方法,可以在最下面的全部代码看到。
self.colorOffset是全局变量,用于设置全局的色值偏差。因为某些屏幕会有色差,所以需要这个设置

定点比色的核心代码是通过QImage类的pixel方法获取到对应的像素点数据,然后转换为QColor对象,再通过QColor对象的getRgb方法获取到对应像素点的RGB色值,然后再与传进来的参数对比,得出结果。

多点比色

def cv2CompareColorMoreMatch(self, lists, _similar=0, border=None, screenQImg=None, isIgnoreBorder=False):if screenQImg == None:screenQImg = self.screen.captureScreen(None, border)startX = 0startY = 0similar = _similar + self.colorOffsetif not isIgnoreBorder and border:startX = border[0]startY = border[1]# print('cv2CompareColorMoreMatch')for x, y, hexColor in lists:color = self.Hex2RGB(hexColor)if int(x)-startX <= 0:print('cv2CompareColorOneMatch error x: '+str(x)+', startX: '+str(startX))if int(y)-startY <= 0:print('cv2CompareColorOneMatch error y: '+str(y)+', startY: '+str(startY))res = QColor(screenQImg.pixel(int(x)-startX, int(y)-startY)).getRgb()if abs(res[0] - color[0]) > similar or abs(res[1] - color[1]) > similar or abs(res[2] - color[2]) > similar:return Falsereturn True

参数:
lists:需要比较色值点的列表,例如:[[998,262,’#fffbeb’], [999,329,’#fffbeb’]]
_similar:色值偏移值,同定点比色
border:截图范围,默认截全屏。同定点比色
screenQImg:截的图片,格式是QImage,默认为空,为空时会根据border截图
isIgnoreBorder:是否忽略截图范围,默认为false。当已有一张全屏图的时候,可以用此参数。例如:graph.cv2CompareColorMoreMatch(pointList,5,border,screenshot,screenshot!=None)
这样就是如果有全屏图就忽略border,否则根据border来截图

多点比色实际上只是支持了多个点对比,核心代码同定点比色。

找色

单点找色

def cv2FindColor(self, hexColor, border=None):color = list(self.Hex2RGB(hexColor))screenImg = self.screen.captureScreen(None, border)array = numpy.array(Image.fromqimage(screenImg))res = numpy.argwhere(numpy.all(array == color, axis=2)).tolist()print('cv2FindColor res: '+str(res))return res

参数:
hexColor:字符串,16进制色值(带#号)
border:截屏范围,默认为全屏
返回值:返回全部色值相同位置的数组

单点找色的核心逻辑,其实就是先将QImage转换为PIL库的Iamge对象,然后通过numpy库的array方法将Image转换为数组以便进行数值操作。
接着使用numpy.all方法比较numpy数组中的每个像素值与指定的RGB色值,返回一个bool数组,表示哪些像素匹配指定颜色。
最后使用numpy.argwhere方法,返回bool数组中值为True的索引,然后通过tolist方法将numpy数组转换为python列表。

一般来说,这个方法比较少用,限制比较多

多点找色

def cv2FindColors(self, hexColorListStr, border=None):screenImg = self.screen.captureScreen(None, border)array = numpy.array(Image.fromqimage(screenImg))startX = 0startY = 0w = Noneh = Noneif border == None:left, top, right, bottom = win32gui.GetWindowRect(self.hwnd)w = right-lefth = bottom-topelse:startX = border[0]startY = border[1]w = border[2]-border[0]h = border[3]-border[1]rgby = []ps = []a = 0firstXY = []res = numpy.empty([0, 2])hexColorStr = hexColorListStr.split(',')for i in hexColorStr:rgb_y = i[-13:]r = int(rgb_y[0:2], 16)g = int(rgb_y[2:4], 16)b = int(rgb_y[4:6], 16)y = int(rgb_y[-2:])rgby.append([r,g,b,y])for i in range(1, len(hexColorStr)):ps.append([int(hexColorStr[i].split('|')[0]), int(hexColorStr[i].split('|')[1])])for i in rgby:result = numpy.logical_and(abs(array[:, :, 0:1] - i[0]) < i[3], abs(array[:, :, 1:2] - i[1]) < i[3], abs(array[:, :, 2:3] - i[2]) < i[3])results = numpy.argwhere(numpy.all(result == True, axis=2)).tolist()if a == 0:firstXY = copy.deepcopy(results)else:nextnextXY = copy.deepcopy(results)for index in nextnextXY:index[0] = int(index[0]) - ps[a - 1][1]index[1] = int(index[1]) - ps[a - 1][0]q = set([tuple(t) for t in firstXY])w = set([tuple(t) for t in nextnextXY])matched = numpy.array(list(q.intersection(w)))if len(matched)==0:return -1,-1res = numpy.append(res, matched, axis=0)a += 1res = res.tolist()for i in res:if res.count(i) == len(hexColorStr) - 1:print('cv2FindColors res: '+str(res))return i[1] + startX, i[0] + startYprint('cv2FindColors not find')return -1,-1

多点找色其实就是大漠插件里的多点找色实现的,其核心还是上述的找色逻辑,这里不再赘述。

识图

单模版匹配

def cv2OneMatchFindImage(self, rect, temp, qimg=None, similar=0.85):img = Noneif qimg:img = cv2.cvtColor(numpy.asarray(Image.fromqimage(qimg)),cv2.COLOR_RGB2BGR)else:img = cv2.cvtColor(numpy.asarray(Image.fromqimage(self.screen.captureScreen(None,rect))),cv2.COLOR_RGB2BGR)template = cv2.cvtColor(numpy.asarray(temp),cv2.COLOR_RGB2BGR)h, w = template.shape[:2]# 匹配模板res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)if max_val >= similar:# 计算矩形左边top_left = max_locbottom_right = (top_left[0] + w, top_left[1] + h)# 返回rect数组,参数分别是topLeft,topRight,bottomLeft,bottomRight,中心点x,中心点yrect = (top_left[0], top_left[1], top_left[0]+w, top_left[1]+h, int(int(2*top_left[0]+w)/2), int(int(2*top_left[1]+h)/2))print('cv2OneMatchFindImage rect: '+str(rect))print('cv2OneMatchFindImage max_val: '+str(max_val))return rectelse:return None

参数:
rect:截图范围,为空截全屏
temp:被查找的图片,小图,PIL库的Image对象
qimg:大图,在这张图上找temp那张图,QImage对象
similar:相似度,默认0.85

模板匹配实际上就是在一张大图中找小图。其核心是基于OpenCV库的cv2.matchTemplate方法。
首先,将两张图片的颜色空间都从RGB转换为BGR,OpenCV使用BGR作为默认颜色空间,然后获取模板图像的高度h和宽度w。
然后通过cv2.matchTemplate方法进行模板匹配,在大图中寻找小图temp的位置,并返回一个二维数组,表示每个位置的匹配结果(此方法有多个不同的匹配方式,试了一下大差不差吧,没有什么最准的)。接着通过cv2.minMaxLoc方法找到最小值和最大值及其对应的位置:
min_val:最小匹配值
max_val:最大匹配值
min_loc:最小值的位置
max_loc:最大值的位置
如果匹配结果的最大匹配值满足相似度要求,则计算顶点和中心点的位置并返回。否则返回空(None)。

注意:单模板匹配只会返回最匹配的一个结果,多模板匹配会返回全部满足相似度要求的结果。

另外,这里要说明一下模板匹配的实现以及问题:
实际使用的情况中,会有时候得不到正确的结果。因此研究了一下内部逻辑,这里简单说一下。
首先看一下OpenCV文档:https://docs.opencv.org/3.4/de/da9/tutorial_template_matching.html
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(文档是英文,这里为了方便翻译为中文截图)
匹配方法有6种:
TM_SQDIFF:平方差匹配法
TM_SQDIFF_NORMED:归一化平方差匹配法
TM_CCORR:相关匹配法
TM_CCORR_NORMED:归一化相关匹配法
TM_CCOEFF:系数匹配法
TM_CCOEFF_NORMED:归一化相关系数匹配法
这里以TM_CCOEFF_NORMED归一化相关系数匹配法为例,公式计算过程详解:
假设有一张大图:
在这里插入图片描述
以及一张小图:
在这里插入图片描述
然后写一个简单的代码进行目标匹配并显示结果
代码:

import cv2
import numpy as np
import matplotlib.pyplot as pltdef match_and_display(image_path, template_path, method, similarity_threshold=0.9):img = cv2.imread(image_path, cv2.IMREAD_COLOR)img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)template = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE)h, w = template.shaperes = cv2.matchTemplate(img_gray, template, method)loc = np.where(res >= similarity_threshold)# 在目标图像上绘制匹配区域的矩形框for pt in zip(*loc[::-1]):top_left = ptbottom_right = (pt[0] + w, pt[1] + h)cv2.rectangle(img, top_left, bottom_right, (0, 255, 0), 2)# 使用 Matplotlib 显示结果图像plt.figure(figsize=(6, 6))plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.title('Matched Results')plt.axis('off')plt.show()

示例调用

image_path = './source.png'
template_path = './temp.png'
method = cv2.TM_CCOEFF_NORMED
match_and_display(image_path, template_path, method, similarity_threshold=0.95)

结果:
TM_SQDIFF(平方差匹配法):
在这里插入图片描述
TM_SQDIFF_NORMED(归一化平方差匹配法):
在这里插入图片描述
TM_CCORR(相关匹配法):
在这里插入图片描述
TM_CCORR_NORMED(归一化相关匹配法):
在这里插入图片描述
TM_CCOEFF:系数匹配法):
在这里插入图片描述
TM_CCOEFF_NORMED:归一化相关系数匹配法)
在这里插入图片描述
从结果可以看到,很多结果都把大图中两个相似的点都识别出来了,甚至还有的匹配方法识别失败了,TM_CCOEFF_NORMED匹配方法看起来是对了,不过当我把相似度降低到0.9时,一样会把大图中左上角的也匹配进结果中:
在这里插入图片描述
从官方文档可以知道,cv2进行模板匹配时,是以模板大小的搜索框依次遍历整张大图的。假设小图宽高为(w,h),大图宽高为(W,H),那么遍历时就绪遍历(W-w+1)次,每列需要遍历(H-h+1)次。
以下列的矩阵为例:
在这里插入图片描述
假设小图的矩阵为:
在这里插入图片描述
根据公式:
在这里插入图片描述
对比公式得出,完全匹配会得到1,完全负相关匹配会得到-1,完全不匹配会得到0
假设匹配的是第一个点,首先两边同时减去各自的均值,得到公式中的T ‘和I’:
在这里插入图片描述 =》 在这里插入图片描述
在这里插入图片描述
=》 在这里插入图片描述
然后求两个矩阵的内积,以及两个矩阵内元素平方和的平方的乘积再开根号:

在这里插入图片描述
result = 6/7.7459 = 0.7746
类似的,我们可以得出,当模板匹配到下面两个矩阵的时候,得出的值也是很接近1的
在这里插入图片描述 =》在这里插入图片描述 =》 在这里插入图片描述
result = 1(完全匹配)
在这里插入图片描述 =》在这里插入图片描述=》在这里插入图片描述
result = -5/5 = -1(完全不匹配)

那么,为什么上述的结果中,当相似度设置为0.9时,会把完全负相关的那一块也匹配到呢。
经过我的计算,当矩阵为
0 0
4 3 时,得到的结果:
在这里插入图片描述
result = 6.5/7.9843 = 0.8140
从结果可以看出,完全负相关周围的矩阵,其实还是有可能匹配到相似度比较高的结果,因此,cv2的模板匹配是有可能不准的。
不过,一般来说,只要取最匹配的值,一般来说结果还是可靠的。
但是,通过这次的探究,使用模板匹配时建议设置的值不低于0.65,这个是我认为比较安全的值,因为按照模板匹配的算法,可能不相关的矩阵也能算出来有0.5的相似度甚至更高,总之使用时不建议相似度设置得太低

多模板匹配

def cv2MoreMatch(self, imagePath, tempImgPath, similar=0.9):img = cv2.imread(imagePath)img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)template = cv2.imread(tempImgPath, 0)h, w = template.shape[:2]res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)# numpy.where返回的坐标值(x,y)是(h,w),注意h,w的顺序loc = numpy.where(res >= similar)rects = []for pt in zip(*loc[::-1]):top_left = ptbottom_right = (pt[0] + w, pt[1] + h)# 返回rect数组,参数分别是topLeft,topRight,bottomLeft,bottomRight,中心点x,中心点yrect = (top_left[0], top_left[1], top_left[0]+w, top_left[1]+h, int(int(2*top_left[0]+w)/2), int(int(2*top_left[1]+h)/2))rects.append(rect)print('cv2MoreMatch rect: '+str(rect))return rects

多模板匹配的参数其实与单模板匹配相同,也是传入大图、小图以及相似度。
不同的是多模板匹配使用了numpy.where方法筛选出符合相似度的结果,并返回的是一个数组。

前台找图

def pyAutoGUIMatch(self, imagePath, rect=None, similar=0.9, grayscale=False):rectInWindow = Noneif rect == None:left, top, right, bottom = win32gui.GetWindowRect(self.hwnd)rectInWindow = (left, top, right-left, bottom-top)print('rectInWindow: '+str(rectInWindow))else:rectInWindow = (rect[0], rect[1], rect[2]-rect[0], rect[3]-rect[1])pos = pyautogui.locateOnScreen(imagePath, region=rectInWindow, confidence=similar, grayscale=grayscale)print('pyAutoGUIMatch pos: '+str(pos))return pos

前台找图是通过pyautogui.locateOnScreen方法实现的,需要注意的是,如果自己的电脑连接了多个屏幕时,此方法无法在第二个屏幕上截图,如果传入的x1值大于屏幕的宽度,会导致报错needle dimension(s) exceed the haystack image or region dimensions

完整代码

#! /usr/bin env python3
# -*- coding:utf-8 -*-
# 图形处理模块import numpy
import cv2
import pyautogui
import win32gui
from Screen import Screen
from PyQt5.QtGui import QColor
from PIL import Image
import copyclass Graph():def __init__(self):self.screen = Screen()self.colorOffset = 0print('Graph init')def bind(self, hwnd):self.hwnd = hwndself.screen.bind(hwnd)def setColorOffset(self, colorOffset):self.colorOffset = colorOffset# 图形处理方法1——使用cv2(默认)  ############################################# 单个模板匹配def cv2OneMatch(self, imagePath, tempImgPath):img = cv2.imread(imagePath)template = cv2.imread(tempImgPath)h, w = template.shape[:2]# 匹配模板res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)# 计算矩形左边top_left = max_locbottom_right = (top_left[0] + w, top_left[1] + h)# 返回rect数组,参数分别是topLeft,topRight,bottomLeft,bottomRight,中心点x,中心点yrect = (top_left[0], top_left[1], top_left[0]+w, top_left[1]+h, int(int(2*top_left[0]+w)/2), int(int(2*top_left[1]+h)/2))print('cv2OneMatch rect: '+str(rect))return rect# 单个模板匹配# @rect 需要被截图的范围(left, right, top, bottom),为空则全窗口截图# @temp 小图,PIL.Image格式# @qimg def cv2OneMatchFindImage(self, rect, temp, qimg=None, similar=0.85):img = Noneif qimg:img = cv2.cvtColor(numpy.asarray(Image.fromqimage(qimg)),cv2.COLOR_RGB2BGR)else:img = cv2.cvtColor(numpy.asarray(Image.fromqimage(self.screen.captureScreen(None,rect))),cv2.COLOR_RGB2BGR)template = cv2.cvtColor(numpy.asarray(temp),cv2.COLOR_RGB2BGR)h, w = template.shape[:2]# 匹配模板res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)if max_val >= similar:# 计算矩形左边top_left = max_locbottom_right = (top_left[0] + w, top_left[1] + h)# 返回rect数组,参数分别是topLeft,topRight,bottomLeft,bottomRight,中心点x,中心点yrect = (top_left[0], top_left[1], top_left[0]+w, top_left[1]+h, int(int(2*top_left[0]+w)/2), int(int(2*top_left[1]+h)/2))print('cv2OneMatchFindImage rect: '+str(rect))print('cv2OneMatchFindImage max_val: '+str(max_val))return rectelse:return None# 多个模板匹配def cv2MoreMatch(self, imagePath, tempImgPath, similar=0.9):img = cv2.imread(imagePath)img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)template = cv2.imread(tempImgPath, 0)h, w = template.shape[:2]res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)# numpy.where返回的坐标值(x,y)是(h,w),注意h,w的顺序loc = numpy.where(res >= similar)rects = []for pt in zip(*loc[::-1]):top_left = ptbottom_right = (pt[0] + w, pt[1] + h)# 返回rect数组,参数分别是topLeft,topRight,bottomLeft,bottomRight,中心点x,中心点yrect = (top_left[0], top_left[1], top_left[0]+w, top_left[1]+h, int(int(2*top_left[0]+w)/2), int(int(2*top_left[1]+h)/2))rects.append(rect)print('cv2MoreMatch rect: '+str(rect))return rectsdef Hex2RGB(self, hex):r = int(hex[1:3], 16)g = int(hex[3:5], 16)b = int(hex[5:7], 16)return r, g, b# 定点比色def cv2CompareColorOneMatch(self, x, y, hexColor, _similar=0, border=None):startX = 0startY = 0similar = _similar + self.colorOffsetif border:startX = border[0]startY = border[1]color = self.Hex2RGB(hexColor)screenQImg = self.screen.captureScreen(None, border)if int(x)-startX <= 0:print('cv2CompareColorOneMatch error x: '+str(x)+', startX: '+str(startX))if int(y)-startY <= 0:print('cv2CompareColorOneMatch error y: '+str(y)+', startY: '+str(startY))res = QColor(screenQImg.pixel(int(x)-startX, int(y)-startY)).getRgb()print('cv2CompareColorOneMatch x: '+str(x)+', y: '+str(y)+', re: '+str(res))if abs(res[0] - color[0]) < similar and abs(res[1] - color[1]) < similar and abs(res[2] - color[2]) < similar:return Trueelse:return False# 多点比色def cv2CompareColorMoreMatch(self, lists, _similar=0, border=None, screenQImg=None, isIgnoreBorder=False):if screenQImg == None:screenQImg = self.screen.captureScreen(None, border)startX = 0startY = 0similar = _similar + self.colorOffsetif not isIgnoreBorder and border:startX = border[0]startY = border[1]# print('cv2CompareColorMoreMatch')for x, y, hexColor in lists:color = self.Hex2RGB(hexColor)if int(x)

完整自动化工程代码:https://gitee.com/chj-self/PythonRobotization

大佬们找到问题欢迎拍砖~

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

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

相关文章

Spring AOP架构设计解析

一、AOP&#xff08;Aspect Oriented Programming&#xff09;Aspect&#xff1a;方面/层面&#xff1b;Oriented&#xff1a;朝向 1、面向方面&#xff08;切面&#xff09;编程 2、Spring基于代理实现AOP 3、业务作用类似于过滤器&#xff0c;比过滤器强大 二、AOP实现方…

基于Java协同过滤算法的电影推荐系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

Kotlin 中的解构

解构声明是 Kotlin 语言的一个特性&#xff0c;它允许我们从一个数据结构中提取多个变量&#xff0c;这样可以让我们的代码更加简洁易读&#xff0c;同时也提高了代码的可维护性。 在 Kotlin 中&#xff0c;解构可以用于多种数据类型&#xff0c;例如&#xff0c;列表&#xf…

vue3文件目录解析

Vue3 的文件目录结构在构建单页面应用时起到了至关重要的作用&#xff0c;其结构清晰、模块化设计有助于提高代码的可读性、可维护性和可重用性。以下是 Vue3 文件目录的详细解析&#xff1a; 根目录&#xff1a; 包含 Vue3 项目的所有主要文件和文件夹。node_modules&#xf…

几何内核开发-实现自己的NURBS曲线生成API

我去年有一篇帖子&#xff0c;介绍了NURBS曲线生成与显示的实现代码。 https://blog.csdn.net/stonewu/article/details/133387469?spm1001.2014.3001.5501文章浏览阅读323次&#xff0c;点赞4次&#xff0c;收藏2次。搞3D几何内核算法研究&#xff0c;必须学习NURBS样条曲线…

前端的拖拽和缩放(缩放以鼠标为中心)

效果&#xff1a; 拖拽和缩放&#xff08;缩放以鼠标为中心&#xff09; 代码具体实现如下&#xff1a; 但是有几个注意点 &#xff08;1&#xff09;为什么需要设置 transform-origin: 0 0; 缩放时以鼠标为中心进行缩放。这意味着需要手动计算缩放过程中元素的位移&#…

动手学深度学习(Pytorch版)代码实践 -卷积神经网络-25使用块的网络VGG

25使用块的网络VGG import torch from torch import nn import liliPytorch as lp import matplotlib.pyplot as plt# 定义VGG块 # num_convs: 卷积层的数量 # in_channels: 输入通道的数量 # out_channels: 输出通道的数量 def vgg_block(num_convs, in_channels, out_channel…

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 &#x1f4da; 前言 &#x1f4d1;摘要 &#x1f4d1;系统流程 &#x1f4da; 系统架构设计 &#x1f4da; 数据库设计 &#x1f4da; 系统功能的具体实现 &#x1f4ac; 系统登录注册 系统登录 登录界面 用户添加 &#x1f4ac; 抗疫列表展示模块 区域信息管理 …

Codeforces Round 954 (Div. 3) A B C D

A. X Axis time limit per test: 2 second memory limit per test: 256 megabytes input: standard input output: standard output You are given three points with integer coordinates x 1 x_1 x1​, x 2 x_2 x2​, and x 3 x_3 x3​ on the X X X axis ( 1 ≤ x i ≤ …

MyBatis 源码分析-- SQL请求执行流程( Mapper 接口方法的执行的过程)

前言 前面我们从源码层面梳理了 SqlSessionFactory、SqlSession 的创建过程及 Mapper 获取过程&#xff0c;本篇我们继续分析一下 Mapper 接口方法的执行的过程&#xff0c;也就是 SQL 的执行流程。 Mybatis 相关知识传送门 初识 MyBatis 【MyBatis 核心概念】 MyBatis 源码…

Anaconda3 常用命令及配置

1、Anaconda是什么? 2、conda常用命令 系统环境&#xff1a;windows10 Anaconda版本&#xff1a;Anaconda3-2024.02-1-Windows-x86_64 2.1、虚拟环境管理 1、查看虚拟环境 conda env list conda info -e 2、创建虚拟环境 # 创建名为 pyenv 的虚拟环境 conda create --na…

计算机软件著作权申请流程及费用_快速登记_经验分享收藏级教程

最近需要申请计算机软件著作权&#xff0c;申请流程走了一遍&#xff0c;整理了分享给大家。软件著作权申请流程及费用&#xff0c;软著快速登记、软著材料及问题解答FAQ&#xff0c;阿里云百科阿里云计算机软件著作权登记20天下证&#xff0c;那么如何申请阿里云软件著作权登记…

【杂记-浅谈OSPF协议各要素及功能】

OSPF协议各要素及功能 一、OSPF协议要素1、COST值2、进程号3、路由及路由器类型4、区域及网络类型5、DR和BDR6、STUB和NSSA区域7、邻居状态机 二、OSPF路由协议中各功能1、报文认证2、路由聚合3、缺省路由4、路由过滤5、多进程6、路由计算7、最小生成树 一、OSPF协议要素 1、C…

MTK7628+MT7612 加PA定频数据

1、硬件型号TR726A5G121-DPA PC9.02.0017。如下所示&#xff1a; 2、WIFI5.8 AC模式 42&#xff08;5120MHz&#xff09;信道&#xff0c;80带宽 3、WIFI5.8 AC模式 38&#xff08;5190MHz&#xff09;信道&#xff0c;40带宽 4、WIFI5.8 AC模式 36&#xff08;5180 MHz&…

微信小程序开发必知必会:文件结构和基本配置

一、微信小程序基本文件结构 1. project.config.json&#xff1a;项目的基本配置文件&#xff0c;包括项目名称、appid、项目目录、页面文件夹等。 {"setting": {"urlCheck": false,"es6": true,"postcss": true,"nodeModulesP…

股票分析学习

库&#xff1a; pandas to_datetime:它可以处理各种格式的日期和时间数据&#xff0c;并将其统一转换为 Pandas 可以理解和操作的内部日期时间格式。 matplotlib.pyplot 用户可以轻松地创建各种静态、动态、交互式和 3D 图形。 1. 绘制线图&#xff08;plot()&#xff09; …

FEP耐酸碱耐高温可定制滴瓶60ml透明四氟瓶F46滴加瓶

FEP滴瓶&#xff1a;又叫聚全氟乙丙烯滴瓶&#xff0c;特氟龙滴瓶。广泛应用于痕量分析、超痕量分析、ICP-MS分析、同位素分析等实验。 主要特性如下&#xff1a; 1.耐高低温&#xff1a;使用温度可达-200&#xff5e;205℃&#xff1b; 2.材质为高纯实验级进口TeflonFEP加工…

虚拟机链接不上usb

传输速度慢 记得换一个支持usb3.0的口和支持usb3.0的线

Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的

Redis的事务功能允许将多个命令打包在一起&#xff0c;然后一次性地执行。这种机制确保了这些命令要么全部执行&#xff0c;要么全部不执行&#xff0c;从而提供了一种原子性的操作。Redis事务是通过以下四个原语实现的&#xff1a; 1. **MULTI**&#xff1a; - 这个命令用…

C语言从入门到进阶(15万字总结)

前言&#xff1a; 《C语言从入门到进阶》这本书可是作者呕心沥血之作&#xff0c;建议零售价1元&#xff0c;当然这里开个玩笑。 本篇博客可是作者之前写的所有C语言笔记博客的集结&#xff0c;本篇博客不止有知识点&#xff0c;还有一部分代码练习。 有人可能会问&#xff…