基于模板匹配的信用卡号码识别系统
本项目实现了一个基于模板匹配的信用卡号码识别系统。
1. 导入库和设置参数
# -*- coding: utf-8 -*-
# 导入工具包
from imutils import contours
import numpy as np
import argparse
import cv2
import myutils
import os# 设置参数
ap = argparse.ArgumentParser()
# 替换为实际的绝对路径
ap.add_argument("-i", "--image", required=False, default=r"F:/cv/creditproject/template-matching-ocr/ocr_a_reference.png",help="path to input image")
ap.add_argument("-t", "--template", required=False, default=r"F:/cv/creditproject/template-matching-ocr/ocr_a_reference.png",help="path to template OCR-A image")
args = vars(ap.parse_args())
- 导入了图像处理、参数解析等所需的库。
- 使用
argparse
模块设置命令行参数,允许用户指定输入图像和模板图像的路径,若未指定则使用默认路径。
2. 定义信用卡类型映射和绘图函数
# 指定信用卡类型
FIRST_NUMBER = {"3": "American Express","4": "Visa","5": "MasterCard","6": "Discover Card"
}
# 绘图展示
def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()
FIRST_NUMBER
字典将信用卡号码的首位数字映射到对应的信用卡类型。cv_show
函数用于显示图像,等待用户按键后关闭窗口。
3. 读取和处理模板图像
# 读取一个模板图像
template_path = args["template"]# 检查文件是否存在
if not os.path.isfile(template_path):print(f"文件不存在: {template_path}")print("请检查文件路径是否正确。")import syssys.exit(1)img = cv2.imread(template_path)# 检查图像是否成功读取
if img is None:print(f"无法打开或读取文件: {template_path}")print("请检查文件路径是否正确,或者文件是否存在。")import syssys.exit(1)
else:cv_show('img', img)# 灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv_show('ref',ref)
# 二值图像
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
cv_show('ref',ref)
- 检查模板文件是否存在并尝试读取图像。
- 将图像转换为灰度图,再进行二值化处理,方便后续轮廓检测。
4. 计算模板图像的轮廓并排序
# 修改解包逻辑,适应 OpenCV 4.x 和 5.x 版本
refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)
cv_show('img', img)
print(f"轮廓数量: {len(refCnts)}")# 若想查看每个轮廓的点数,可以遍历 refCnts
for i, cnt in enumerate(refCnts):print(f"轮廓 {i} 的点数: {cnt.shape[0]}")
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0] #排序,从左到右,从上到下
digits = {}# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):# 计算外接矩形并且resize成合适大小(x, y, w, h) = cv2.boundingRect(c)roi = ref[y:y + h, x:x + w]roi = cv2.resize(roi, (57, 88))# 每一个数字对应每一个模板digits[i] = roi
- 使用
cv2.findContours
函数检测二值图像的轮廓。 - 绘制轮廓并显示图像,打印轮廓数量和每个轮廓的点数。
- 对轮廓进行排序,提取每个轮廓的外接矩形区域并调整大小,存储在
digits
字典中作为模板。
5. 读取和预处理输入图像
# 初始化卷积核
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))#读取输入图像,预处理
image = cv2.imread(args["image"])
cv_show('image',image)
image = myutils.resize(image, width=300)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv_show('gray',gray)#礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
cv_show('tophat',tophat)
#
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, #ksize=-1相当于用3*3的ksize=-1)gradX = np.absolute(gradX)
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
gradX = gradX.astype("uint8")print (np.array(gradX).shape)
cv_show('gradX',gradX)
- 初始化卷积核,用于形态学操作。
- 读取输入图像,调整大小并转换为灰度图。
- 使用礼帽操作突出明亮区域,再使用 Sobel 算子计算水平梯度,对梯度值进行归一化处理。
6. 对梯度图像进行形态学操作并检测轮廓
#通过闭操作(先膨胀,再腐蚀)将数字连在一起
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
cv_show('gradX',gradX)
#THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
thresh = cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
cv_show('thresh',thresh)#再来一个闭操作thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel) #再来一个闭操作
cv_show('thresh',thresh)# 计算轮廓
threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = threshCnts
cur_img = image.copy()
cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)
cv_show('img', cur_img)
- 对梯度图像进行闭操作,将数字连在一起。
- 使用 Otsu 阈值法进行二值化处理,再进行一次闭操作。
- 检测二值图像的轮廓并绘制在图像上。
7. 筛选和排序符合条件的轮廓
locs = []# 遍历轮廓
for (i, c) in enumerate(cnts):# 计算矩形(x, y, w, h) = cv2.boundingRect(c)ar = w / float(h)# 选择合适的区域,根据实际任务来,这里的基本都是四个数字一组if ar > 2.5 and ar < 4.0:if (w > 40 and w < 55) and (h > 10 and h < 20):#符合的留下来locs.append((x, y, w, h))# 将符合的轮廓从左到右排序
locs = sorted(locs, key=lambda x:x[0])
- 遍历所有轮廓,计算每个轮廓的外接矩形和宽高比。
- 根据宽高比和矩形尺寸筛选出符合条件的轮廓,存储在
locs
列表中并排序。
8. 识别每个轮廓中的数字并输出结果
output = []# 遍历每一个轮廓中的数字
for (i, (gX, gY, gW, gH)) in enumerate(locs):# initialize the list of group digitsgroupOutput = []# 根据坐标提取每一个组group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]cv_show('group',group)# 预处理group = cv2.threshold(group, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]cv_show('group',group)# 计算每一组的轮廓digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)digitCnts = contours.sort_contours(digitCnts,method="left-to-right")[0]# 计算每一组中的每一个数值for c in digitCnts:# 找到当前数值的轮廓,resize成合适的的大小(x, y, w, h) = cv2.boundingRect(c)roi = group[y:y + h, x:x + w]roi = cv2.resize(roi, (57, 88))cv_show('roi',roi)# 计算匹配得分scores = []# 在模板中计算每一个得分for (digit, digitROI) in digits.items():# 模板匹配result = cv2.matchTemplate(roi, digitROI,cv2.TM_CCOEFF)(_ , score, _, _) = cv2.minMaxLoc(result)scores.append(score)# 得到最合适的数字groupOutput.append(str(np.argmax(scores)))# 画出来cv2.rectangle(image, (gX - 5, gY - 5),(gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)cv2.putText(image, "".join(groupOutput), (gX, gY - 15),cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)# 得到结果output.extend(groupOutput)# 打印结果
if len(output) == 0:print("未识别到有效的信用卡号码,请检查输入图像或调整识别参数。")
else:first_digit = output[0]if first_digit in FIRST_NUMBER:print("Credit Card Type: {}".format(FIRST_NUMBER[first_digit]))print("Credit Card #: {}".format("".join(output)))else:print("无法根据首位数字 {} 确定信用卡类型,请检查识别结果。".format(first_digit))cv2.imshow("Image", image)
cv2.waitKey(0)
- 遍历筛选后的轮廓,提取每个轮廓区域并进行预处理。
- 检测每个区域内的数字轮廓,使用模板匹配方法识别每个数字。
- 在图像上绘制识别结果,根据识别结果输出信用卡类型和号码。
ocr_template_match.py
# -*- coding: utf-8 -*-
# 导入工具包,contours 用于轮廓排序,numpy 用于数值计算,argparse 用于命令行参数解析
# cv2 是 OpenCV 库,用于计算机视觉任务,myutils 是自定义工具包,os 用于文件操作
from imutils import contours
import numpy as np
import argparse
import cv2
import myutils
import os# 设置参数,使用 argparse 模块创建一个参数解析器
ap = argparse.ArgumentParser()
# 定义输入图像的路径参数,若未提供则使用默认值
ap.add_argument("-i", "--image", required=False, default=r"F:/cv/creditproject/template-matching-ocr/ocr_a_reference.png",help="path to input image")
# 定义模板图像的路径参数,若未提供则使用默认值
ap.add_argument("-t", "--template", required=False, default=r"F:/cv/creditproject/template-matching-ocr/ocr_a_reference.png",help="path to template OCR-A image")
# 解析命令行参数并转换为字典形式
args = vars(ap.parse_args())# 指定信用卡类型,将信用卡号码的首位数字映射到对应的信用卡类型
FIRST_NUMBER = {"3": "American Express","4": "Visa","5": "MasterCard","6": "Discover Card"
}# 绘图展示函数,用于显示图像并等待用户按键后关闭窗口
def cv_show(name,img):cv2.imshow(name, img)cv2.waitKey(0)cv2.destroyAllWindows()# 读取一个模板图像,从命令行参数中获取模板图像的路径
template_path = args["template"]# 检查文件是否存在,若不存在则打印错误信息并退出程序
if not os.path.isfile(template_path):print(f"文件不存在: {template_path}")print("请检查文件路径是否正确。")import syssys.exit(1)# 读取模板图像
img = cv2.imread(template_path)# 检查图像是否成功读取,若读取失败则打印错误信息并退出程序
if img is None:print(f"无法打开或读取文件: {template_path}")print("请检查文件路径是否正确,或者文件是否存在。")import syssys.exit(1)
else:# 若读取成功,显示模板图像cv_show('img', img)# 将模板图像转换为灰度图
ref = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 显示灰度图
cv_show('ref',ref)# 将灰度图转换为二值图像,使用阈值 10,将背景设为黑色,数字设为白色
ref = cv2.threshold(ref, 10, 255, cv2.THRESH_BINARY_INV)[1]
# 显示二值图
cv_show('ref',ref)# 计算轮廓,cv2.findContours() 函数接受的参数为二值图,只检测外轮廓,只保留终点坐标
# 返回的 list 中每个元素都是图像中的一个轮廓
# 修改解包逻辑,适应 OpenCV 4.x 和 5.x 版本
refCnts, hierarchy = cv2.findContours(ref.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 在原始图像上绘制轮廓,颜色为红色,线宽为 3
cv2.drawContours(img, refCnts, -1, (0, 0, 255), 3)
# 显示绘制轮廓后的图像
cv_show('img', img)
# 打印检测到的轮廓数量
print(f"轮廓数量: {len(refCnts)}")# 若想查看每个轮廓的点数,可以遍历 refCnts
for i, cnt in enumerate(refCnts):print(f"轮廓 {i} 的点数: {cnt.shape[0]}")# 对轮廓进行排序,从左到右,从上到下
refCnts = myutils.sort_contours(refCnts, method="left-to-right")[0]
# 初始化一个字典,用于存储每个数字对应的模板
digits = {}# 遍历每一个轮廓
for (i, c) in enumerate(refCnts):# 计算当前轮廓的外接矩形(x, y, w, h) = cv2.boundingRect(c)# 从二值图中提取外接矩形区域roi = ref[y:y + h, x:x + w]# 将提取的区域调整为固定大小 (57, 88)roi = cv2.resize(roi, (57, 88))# 将每个数字对应的模板存储到字典中digits[i] = roi# 初始化卷积核,用于形态学操作
rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3))
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))# 读取输入图像
image = cv2.imread(args["image"])
# 显示输入图像
cv_show('image',image)
# 调整输入图像的宽度为 300
image = myutils.resize(image, width=300)
# 将输入图像转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 显示灰度图
cv_show('gray',gray)# 礼帽操作,突出更明亮的区域
tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, rectKernel)
# 显示礼帽操作后的图像
cv_show('tophat',tophat) # 使用 Sobel 算子计算水平梯度,ksize=-1 相当于使用 3*3 的核
gradX = cv2.Sobel(tophat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)# 取梯度的绝对值
gradX = np.absolute(gradX)
# 获取梯度的最小值和最大值
(minVal, maxVal) = (np.min(gradX), np.max(gradX))
# 对梯度值进行归一化处理,将其映射到 0-255 范围
gradX = (255 * ((gradX - minVal) / (maxVal - minVal)))
# 将梯度值转换为 uint8 类型
gradX = gradX.astype("uint8")# 打印梯度图像的形状
print (np.array(gradX).shape)
# 显示梯度图像
cv_show('gradX',gradX)# 通过闭操作(先膨胀,再腐蚀)将数字连在一起
gradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)
# 显示闭操作后的图像
cv_show('gradX',gradX)# 使用 Otsu 阈值法进行二值化处理,自动寻找合适的阈值
thresh = cv2.threshold(gradX, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 显示二值化后的图像
cv_show('thresh',thresh)# 再来一个闭操作
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)
# 显示再次闭操作后的图像
cv_show('thresh',thresh)# 计算二值图像的轮廓
threshCnts, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)# 将检测到的轮廓赋值给 cnts
cnts = threshCnts
# 复制一份输入图像
cur_img = image.copy()
# 在复制的图像上绘制轮廓,颜色为红色,线宽为 3
cv2.drawContours(cur_img, cnts, -1, (0, 0, 255), 3)
# 显示绘制轮廓后的图像
cv_show('img', cur_img)# 初始化一个列表,用于存储符合条件的轮廓的外接矩形信息
locs = []# 遍历轮廓
for (i, c) in enumerate(cnts):# 计算当前轮廓的外接矩形(x, y, w, h) = cv2.boundingRect(c)# 计算外接矩形的宽高比ar = w / float(h)# 选择合适的区域,根据实际任务,这里基本都是四个数字一组if ar > 2.5 and ar < 4.0:if (w > 40 and w < 55) and (h > 10 and h < 20):# 符合条件的外接矩形信息添加到列表中locs.append((x, y, w, h))# 将符合的轮廓从左到右排序
locs = sorted(locs, key=lambda x:x[0])# 初始化一个列表,用于存储最终识别的信用卡号码
output = []# 遍历每一个轮廓中的数字
for (i, (gX, gY, gW, gH)) in enumerate(locs):# 初始化一个列表,用于存储当前组的数字识别结果groupOutput = []# 根据坐标提取每一个组group = gray[gY - 5:gY + gH + 5, gX - 5:gX + gW + 5]# 显示提取的组图像cv_show('group',group)# 对提取的组图像进行预处理,使用 Otsu 阈值法进行二值化处理group = cv2.threshold(group, 0, 255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]# 显示预处理后的组图像cv_show('group',group)# 计算每一组的轮廓digitCnts, hierarchy = cv2.findContours(group.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)# 对每一组的轮廓进行排序,从左到右digitCnts = contours.sort_contours(digitCnts,method="left-to-right")[0]# 计算每一组中的每一个数值for c in digitCnts:# 找到当前数值的轮廓,计算其外接矩形(x, y, w, h) = cv2.boundingRect(c)# 从二值化的组图像中提取当前数值的区域roi = group[y:y + h, x:x + w]# 将提取的区域调整为固定大小 (57, 88)roi = cv2.resize(roi, (57, 88))# 显示提取的数值区域cv_show('roi',roi)# 计算匹配得分scores = []# 在模板中计算每一个得分for (digit, digitROI) in digits.items():# 模板匹配result = cv2.matchTemplate(roi, digitROI,cv2.TM_CCOEFF)# 获取匹配结果的最大值和其位置(_ , score, _, _) = cv2.minMaxLoc(result)# 将得分添加到列表中scores.append(score)# 得到最合适的数字,取得分最高的模板对应的数字groupOutput.append(str(np.argmax(scores)))# 在原始图像上绘制矩形框和识别结果cv2.rectangle(image, (gX - 5, gY - 5),(gX + gW + 5, gY + gH + 5), (0, 0, 255), 1)cv2.putText(image, "".join(groupOutput), (gX, gY - 15),cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 0, 255), 2)# 将当前组的识别结果添加到最终结果列表中output.extend(groupOutput)# 打印结果
if len(output) == 0:print("未识别到有效的信用卡号码,请检查输入图像或调整识别参数。")
else:# 获取识别结果的首位数字first_digit = output[0]if first_digit in FIRST_NUMBER:print("Credit Card Type: {}".format(FIRST_NUMBER[first_digit]))print("Credit Card #: {}".format("".join(output)))else:print("无法根据首位数字 {} 确定信用卡类型,请检查识别结果。".format(first_digit))# 显示最终识别结果的图像
cv2.imshow("Image", image)
# 等待用户按键
cv2.waitKey(0)
myutils.py
import cv2def sort_contours(cnts, method="left-to-right"):reverse = Falsei = 0if method == "right-to-left" or method == "bottom-to-top":reverse = Trueif method == "top-to-bottom" or method == "bottom-to-top":i = 1boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),key=lambda b: b[1][i], reverse=reverse))return cnts, boundingBoxes
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):dim = None(h, w) = image.shape[:2]if width is None and height is None:return imageif width is None:r = height / float(h)dim = (int(w * r), height)else:r = width / float(w)dim = (width, int(h * r))resized = cv2.resize(image, dim, interpolation=inter)return resized
相关文章:
基于模板匹配的信用卡号码识别系统
本项目实现了一个基于模板匹配的信用卡号码识别系统。 1. 导入库和设置参数 # -*- coding: utf-8 -*- # 导入工具包 from imutils import contours import numpy as np import argparse import cv2 import myutils import os# 设置参数 ap argparse.ArgumentParser() # 替换…...
Spring Boot中Excel处理完全指南
文章目录 1. Excel处理基础知识1.1 为什么需要在应用中处理Excel文件?1.2 Java中的Excel处理库介绍1.2.1 Apache POI1.2.2 EasyExcel1.2.3 JExcel1.2.4 Apache POI SXSSF1.3 Spring Boot中集成Excel处理2. 在Spring Boot中集成Excel处理库2.1 集成Apache POI2.1.1 添加依赖2.1…...
洛谷P1312 [NOIP 2011 提高组] Mayan 游戏
题目 #算法/进阶搜索 思路: 根据题意,我们可以知道,这题只能枚举,剪枝,因此,我们考虑如何枚举,剪枝. 首先,我们要定义下降函数down(),使得小木块右移时,能够下降到最低处,其次,我们还需要写出判断函数,判断矩阵内是否有小木块没被消除.另外,我们还需要消除函数,将矩阵内三个相连…...
c++ (异常)
1.异常的概念及使用 1.1异常的概念 异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理, 异常使得我们能够将问题的检测与解决问题的过程分开,程序的一部分负责检测问题的出现,然后 解决问题的任务传…...
MySQL如何实现行行比较
概述 在MySQL中实现行行比较通常涉及比较同一表或不同表中不同行的数据。以下是几种常见的方法及示例: 1. 自连接(Self-Join) 通过将表与自身连接,比较不同行的数据。 场景示例:比较同一用户相邻订单的金额差异。 …...
springboot2.X创建maven多模块工程
因为需要,所以付出。 好长时间没有搭建新的框架了,最近在搭建微服务的多模块maven工程,现在就将创建的过程记录下来,方便自学的小伙伴找寻资料,少走弯路。好了下面直接开干。 开发工具 :idea 、springboo…...
八股文---Redis(1)
目录 1.Redis-使用场景 1.我看你做的项目中,都用到了redis,你在最近的项目中哪些场景使用了redis呢? 2.缓存三兄弟可以我看我另一个文章(穿透,雪崩,击穿) 3.redis做为缓存,mysql…...
QT聊天项目DAY06
1.从git上同步项目 编译测试,编译通过 Post请求测试 测试成功 2. email is 打印有问题,检查 解析结果是存储在jsonResult中的,修改 3. 客户端实现Post验证码请求 3.1 同步Qt客户端项目 检查QT版本,由于我在公司用的还是QT5.12.9…...
python(八)-数据类型转换
#数据类型转换 #转换为整型int #字符串str--》整数int #纯数字的字符串可以转换,否则会报错 s 2025 n int(s) print(type(s),type(n)) print(n)#浮点数float--》整数int s1 2.23 print(int(s1))#bool-->整数int s2,s3 True,False print(int(s2),int(s3))#转…...
JavaScript 变量命名规范
在编写JavaScript代码时,遵循良好的变量命名规范对于提高代码的可读性、可维护性和协作效率至关重要。一个清晰且一致的命名习惯不仅有助于开发者自己理解代码,也能让其他团队成员更容易上手和维护项目。本文将详细介绍JavaScript中常见的变量命名规则和…...
2025年渗透测试面试题总结-拷打题库05(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 2025年渗透测试面试题总结-拷打题库05 1. 病毒和蠕虫的区别 2. DNS欺骗(DNS Spoofing&…...
【排队论】Probabilistic Forecasts of Bike-Sharing Systems for Journey Planning
Probabilistic Forecasts of Bike-Sharing Systems forJourney Planning abstract 我们研究了对共享单车系统(BSS)车站未来自行车可用性进行预测的问题。这是相关的,以便提出建议,保证用户能够进行旅行的概率足够高。为此&#x…...
Redis 的持久化机制(RDB, AOF)对微服务的数据一致性和恢复性有何影响?如何选择?
Redis 的持久化机制(RDB 和 AOF)对于保证 Redis 服务重启或崩溃后数据的恢复至关重要,这直接影响到依赖 Redis 的微服务的数据一致性和恢复能力。 1. RDB (Redis Database Backup) 机制: 在指定的时间间隔内,将 Redis 在内存中的…...
手撕LLM(四):从源码出发,探索大模型的预训练(pretrain)过程
前面我们基于Minimind项目介绍了大模型的推理、LoRa加载、Moe结构, 大家对大模型的整体结构应该有一个比较清晰的认识;从该篇博客开始,我们通过代码剖析大模型的训练过程,今天的主题是大模型的预训练。 那大模型的预训练是一个什么…...
Linux系统:进程终止的概念与相关接口函数(_exit,exit,atexit)
本节目标 理解进程终止的概念理解退出状态码的概念以及使用方法掌握_exit与exit函数的用法以及区别atexit函数注册终止时执行的函数相关宏 一、进程终止 进程终止(Process Termination)是指操作系统结束一个进程的执行,回收其占用的资源&a…...
keil5 µVision 升级为V5.40.0.0:增加了对STM32CubeMX作为全局生成器的支持,主要有哪些好处?
在Keil5 μVision V5.40.0.0版本中,增加了对STM32CubeMX作为全局生成器的支持,这一更新主要带来了以下三方面的提升: 开发流程整合STM32CubeMX原本就支持生成Keil项目代码,但新版本将这一集成升级为“全局生成器”级别,意味着STM32CubeMX生成的代码能直接成为Keil项目的核…...
C 语言联合与枚举:自定义类型的核心解析
上篇博客中,我们通过学习了解了C语言中一种自定义类型结构体的相关知识,那么该语言中是否还拥有相似的自定义类型呢?这将是我们今天学习的目标。 1.联合体 联合体其实跟结构体类似,也是由一个或多个成员构成,这些成员…...
P1113 杂务-拓扑排序
拓扑排序 P1113 杂务 题目来源-洛谷 题意 求出完成所有任务的最短时间 思路 要求完成所有任务的最短时间,即每个任务尽可能最短,所以再求完成所有任务中的最大值(需要最长时间的任务都完成了才叫全部完成) 问题化解…...
Flink介绍——实时计算核心论文之Kafka论文总结
引入 大数据系统中的数据来源 在开始深入探讨Kafka之前,我们得先搞清楚一个问题:大数据系统中的数据究竟是从哪里来的呢?其实,这些数据大部分都是由各种应用系统或者业务系统产生的“日志”。 比如,互联网公司的广告…...
模拟投资大师思维:AI对冲基金开源项目详解
这里写目录标题 引言项目概述核心功能详解多样化的AI投资智能体灵活的运行模式透明的决策过程 安装和使用教程环境要求安装步骤基本使用方法运行对冲基金模式运行回测模式 应用场景和实际价值教育和研究价值潜在的商业应用与现有解决方案的对比局限性与发展方向 结论 引言 随着…...
DAY4:数据库对象与高级查询深度解析:从视图到多表关联实战
一、数据库对象精要指南 1.1 视图(View)的进阶应用 视图是存储在数据库中的虚拟表,本质是预编译的SQL查询语句。通过视图可以简化复杂查询、实现数据安全隔离、保持业务逻辑一致性。 创建语法示例: CREATE VIEW sales_summary…...
【Matlab】中国东海阴影立体感地图
【Matlab】中国东海阴影立体感地图 【Matlab】中国东海阴影立体感地图 【Matlab】中国东海阴影图立体感画法 以前分享过一次,链接如下: 中国海域地形图 但是以前还是有些小问题,这次修改了。 另外,增加了新的画法: 另…...
python文件类操作:json/ini配置文件、logging日志统计、excel表格数据读写、os操作库
文章目录 一、with open文件操作二、csv表格数据读写三、Excel表格数据读写四、json配置文件读写五、ini配置文件读写六、logging日志统计七、os操作库(文件拼接、创建、判断等) 打开文件使用不同参数有着不同的含义,比如只读、只写、二进制读…...
VSCode安装与环境配置(Mac环境)
20250419 - 概述 大概是非常久之前了,装了VSCode,估计都得21的时候了,电脑上也没更新过。当时安装也直接装上就完事了。这次把版本更新一下,同时记录一下这个安装过程。 安装 mac下安装非常简单,直接从官网下载&am…...
【信息系统项目管理师】高分论文:论信息系统项目的采购管理(“营业工单系统”项目)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划采购管理2、实施采购3、控制采购论文 2018年1月,我参加了 XX运营商集团公司某省分公司的“营业工单系统”的信息化建设项目,我有幸担任项目经理。该项目投资1000万元人民币,建设工期为12个月。该…...
XCVU13P-2FHGA2104I Xilinx Virtex UltraScale+ FPGA
XCVU13P-2FHGA2104I 是 Xilinx(现为 AMD)Virtex UltraScale™ FPGA 系列中的高端 Premium 器件,基于 16nm FinFET 工艺并采用 3D IC 堆叠硅互连(SSI)技术,提供业内顶级的计算密度和带宽。该芯片集成约 3,…...
@Validated与@Valid的正确使用姿势
验证代码 Validated RestController public class A {PostMappingpublic void test(Min(value 1) Integer count) {} // 校验规则生效 }RestController public class A {PostMappingpublic void test(Validated Min(value 1) Integer count) {} // 校验规则不生效 }RestCont…...
Ubuntu20.04下Docker方案实现多平台SDK编译
0 前言 熟悉嵌入式平台Linux SDK编译流程的小伙伴都知道,假如平台a要求必须在Ubuntu18.04下编译,平台b要求要Ubuntu22.04的环境,那我只有Ubuntu20.04,或者说我的电脑硬件配置最高只能支持Ubuntu20.04怎么办?强行在Ubuntu20.04下编译,编又编不过,换到旧版本我又不愿意,…...
树莓派超全系列教程文档--(34)树莓派配置GPIO
配置GPIO GPIO控制gpio 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 GPIO控制 gpio 通过 gpio 指令,可以在启动时将 GPIO 引脚设置为特定模式和值,而以前需要自定义 dt-blob.bin 文件。每一行都对一组引脚应用相同的设…...
C语言 数组(下)
目录 1.二维数组的创建 2.二位数组的初始化 3.二维数组的使用 4.二维数组在内存中的储存 1.二维数组的创建 1.1二维数组的概念 前面学习的数组被称为一维数组,数组的元素都是内置类型的,如果我们把一维数组做为数组的元 素,这时候就是…...
opencv图像旋转(单点旋转的原理)
首先我们以最简单的一个点的旋转为例子,且以最简单的情况举例,令旋转中心为坐标系中心O(0,0),假设有一点P_{0}(x_{0},y_{0}),P_{0}离旋转中心O的距离为r,OP_{0}与坐标轴x轴的夹角为\…...
针对MCP认证考试中的常见技术难题进行实战分析与解决方案分享
一、身份与权限管理类难题 场景1:Active Directory组策略(GPO)不生效 问题现象:客户端计算机未应用新建的组策略。排查步骤: 检查GPO链接顺序:使用gpresult /r查看策略优先级,确保目标OU的GPO…...
systemctl管理指令
今天我们来继续学习服务管理指令,接下来才是重头戏-systemctl,那么话不多说,直接开始吧. systemctl管理指令 1.基本语法: systemctl [start | stop | restart | status]服务 注:systemctl指令管理的服务在/usr/lib/ systemd/system查看 2.systemctl设置服务的自…...
DataWhale AI春训营 问题汇总
1.没用下载训练集导致出错,爆错如下。 这个时候需要去比赛官网下载对应的初赛训练集 unzip -d /mnt/workspace/sais_third_new_energy_baseline/data /mnt/workspace/sais_third_new_energy_baseline/初赛训练集.zip 在命令行执行这个命令解压 2.没定义测试集 te…...
当算力遇上马拉松:一场科技与肉身的极限碰撞
目录 一、从"肉身苦修"到"科技修仙" 二、马拉松的"新大陆战争" 三、肉身会被算法"优化"吗? 马拉松的下一站是"人机共生"时代 当AI能预测你的马拉松成绩,算法能规划最佳补给方案,智能装备让训练效率翻倍——你还会用传…...
n8n 中文系列教程_02. 自动化平台深度解析:核心优势与场景适配指南
在低代码与AI技术深度融合的今天,n8n作为开源自动化平台正成为开发者提效的新利器。本文深度剖析其四大核心技术优势——极简部署、服务集成、AI工作流与混合开发模式,并基于真实场景测试数据,厘清其在C端高并发、多媒体处理等场景的边界。 一…...
Macvlan 网络类型详解:特点、优势与局限性
一、Macvlan 网络类型的基本概念 1. 什么是 Macvlan Macvlan 是 Linux 内核提供的一种网络虚拟化技术,允许在单个物理接口(例如 enp0s3)上创建多个虚拟网络接口。每个虚拟接口拥有独立的 MAC 地址,表现得像物理网络中的独立设备…...
tigase源码学习杂记-AbstractMessageReceiver
前言 废话,最近把工作中用的基于XMPP协议的经典开源框架又读了一遍,整理一下其优秀的源码学习记录。 概述 AbstractMessageReceiver是tigase核心组件MessageRouter、SessionManager的抽象父类,是tigase消息接收器的抽象。AbstractMessageR…...
C#.net core部署IIS
Windows IIS 部署 .NET 应用详细指南 本文档提供了在 Windows Server 上使用 IIS 部署 .NET 应用(包括 .NET Core 和传统 WebForms)的完整步骤和最佳实践。 目录 概述环境准备.NET Core 应用部署 应用准备发布应用在 IIS 中配置应用池配置高级配置 .N…...
sql学习
Name 列中选取唯一不同的值 插入 更新 删除 筛选固定的行数 模糊查询 包含 范围 name的别名是n 两个表交集 左边包含全部 右边包含全部 重复的展示一条 重复的都会展示 创建一个新表,把字段复制近期 创建数据库 约束 创建索引 删除 函数 聚合函数...
OSPF实验
实验要求: 1.R5为ISP,其上只能配置IP地址;R4作为企业边界路由器, 出口公网地址需要通过PPP协议获取,并进行chap认证 (上面这个不会做) 2.整个OSPF环境IP基于172.16.0.0/16划分; 3.所…...
洛谷题目:P8624 [蓝桥杯 2015 省 AB] 垒骰子 题解 (本题简)
题目传送门: P8624 [蓝桥杯 2015 省 AB] 垒骰子 - 洛谷 (luogu.com.cn) 前言: 这道题要求我们计算将 个骰子垒成柱体且满足某些面不能紧贴的不同垒骰字方式的数量,并且结果需要对 取模。下面小亦来带大家逐步分析解题思路: #基本概念理解: 1、骰子特性: 一直骰子的…...
简单线段树的讲解(一点点的心得体会)
目录 一、初识线段树 图例: 编辑 数组存储: 指针存储: 理由: build函数建树 二、线段树的区间修改维护 区间修改维护: 区间修改的操作: 递归更新过程: 区间修改update:…...
在 Node.js 中使用原生 `http` 模块,获取请求的各个部分:**请求行、请求头、请求体、请求路径、查询字符串** 等内容
在 Node.js 中使用原生 http 模块,可以通过 req 对象来获取请求的各个部分:请求行、请求头、请求体、请求路径、查询字符串 等内容。 ✅ 一、基础结构 const http require(http); const url require(url);const server http.createServer((req, res)…...
深度学习--mnist数据集实现卷积神经网络的手写数字识别
文章目录 一、卷积神经网络CNN1、什么是CNN2、核心3、构造 二、案例1、下载数据集(训练、测试集)并展示画布2、打包数据图片3、判断系统使用的是CPU还是GPU4、定义CNN神经网络5、训练和测试模型 一、卷积神经网络CNN 1、什么是CNN 卷积神经网络是一种深…...
python基础知识点(1)
python语句 一行写一条语句 一行内写多行语句,使用分号分隔建议每行写一句,且结束时不写分号写在[ ]、{ }内的跨行语句,被视为一行语句\ 是续行符,实现分行书写功能 反斜杠表示下一行和本行是同一行 代码块与缩进 代码块复合语句…...
详解反射型 XSS 的后续利用方式:从基础窃取到高级组合拳攻击链
在网络安全领域,反射型跨站脚本攻击(Reflected Cross-Site Scripting,简称反射型 XSS)因其短暂的生命周期和临时性,常被视为“低危”漏洞,威胁性不如存储型或 DOM 型 XSS。然而,这种看法低估了它…...
【问题笔记】解决python虚拟环境运行脚本无法激活问题
【问题笔记】解决python虚拟环境运行脚本无法激活问题 错误提示问题所在解决方法**方法 1:临时更改执行策略****方法 2:永久更改执行策略** **完整流程示例** 错误提示 PS F:\PythonProject\0419graphrag-local-ollama-main> venv1\Scripts\activate…...
CF148D Bag of mice
题目传送门 思路 状态设计 设 d p i , j dp_{i, j} dpi,j 表示袋中有 i i i 个白鼠和 j j j 个黑鼠时, A A A 能赢的概率。 状态转移 现在考虑抓鼠情况: A A A 抓到白鼠:直接判 A A A 赢,概率是 i i j \frac{i}{i j}…...
精益数据分析(6/126):深入理解精益分析的核心要点
精益数据分析(6/126):深入理解精益分析的核心要点 在创业和数据驱动的时代浪潮中,我们都在不断探索如何更好地利用数据推动业务发展。我希望通过和大家分享对《精益数据分析》的学习心得,一起在这个充满挑战和机遇的领…...