机器学习方法实现数独矩阵识别器
目录
导包
工具函数构建说明
1. 基础图像处理工具
2. 图像预处理模块
3. 数独轮廓检测与定位
4. 网格划分与单元格提取
5. 数字特征提取
6. 多网格处理流程
数据流分析
核心算法详解
核心机器视觉方法
1. 透视变换校正算法
2. 数字区域提取算法
3. 多网格检测算法
运行效果
脚本评估
设计模式与扩展性
1. 模块化设计
2. 扩展性分析
潜在优化方向
完整代码
延伸用途
项目目的:将图片中的三个数独矩阵进行识别并一一切分出来
核心使用opencv-python进行机器视觉算法代码构建
导包
import cv2
import operator
import numpy as np
import os
from datetime import datetime
工具函数构建说明
从功能模块、数据流和核心算法三个方面展开
1. 基础图像处理工具
def show_image(img, win='image'):"""显示图片,直到按下任意键继续"""def show_digits(digits, color=255, withBorder=True, grid_num=1):"""将提取并处理过的81个单元格图片构成的列表显示为二维9*9大图"""def convert_with_color(color, img):"""如果color是元组且img是灰度图,则动态地转换img为彩图"""
功能:提供图像显示、多图拼接和色彩模式转换等基础工具
依赖:OpenCV的图像显示和操作函数
2. 图像预处理模块
def pre_process_gray(gray, skip_dilate=False):"""使用高斯模糊、自适应阈值分割和/或膨胀来暴露图像的主特征"""
处理流程:高斯模糊→自适应阈值分割→形态学膨胀
关键参数:高斯核大小(9,9)、阈值方法:ADAPTIVE_THRESH_GAUSSIAN_C
3. 数独轮廓检测与定位
def find_corners_of_largest_polygon(bin_img):"""找出图像中面积最大轮廓的4个角点。"""def distance_between(p1, p2):"""返回两点之间的标量距离"""def crop_and_warp(gray, crop_rect):"""将灰度图像中由4角点围成的四边形区域裁剪出来,并将其扭曲为类似大小的正方形"""
算法逻辑:
1. 轮廓检测与排序(按面积降序)
2. 角点定位(基于坐标和与坐标差)
3. 透视变换校正
4. 网格划分与单元格提取
def infer_grid(square_gray):"""从正方形灰度图像推断其内部81个单元网格的位置(以等分方式)。"""def cut_from_rect(img, rect):"""从图像中切出一个矩形ROI区域。"""
划分方法:将校正后的正方形图像平均分割为9×9网格
数据结构:每个单元格由左上角和右下角坐标表示
5. 数字特征提取
def find_largest_feature(inp_img, scan_tl, scan_br):"""利用floodFill函数返回它所填充区域的边界框的事实,找到图像中的主特征"""def extract_digit(bin_img, rect, size):"""从预处理后的二值方形大格子图中提取由rect指定的小单元格数字图"""def scale_and_centre(img, size, margin=0, background=0):"""把单元格图片img经缩放且加边距,置于边长为size的新背景正方形图像中"""
核心算法:
1. 区域生长(floodFill)定位数字主体
2. 边界框提取与裁剪
3. 缩放归一化处理
6. 多网格处理流程
def find_sudoku_grids(image_path):"""定位图像中的所有数独图"""def parse_multiple_grids(image_path):"""处理包含多个数独图的图像"""def order_points(pts):"""将四个角点按左上、右上、右下、左下顺序排列"""
处理流程:
1. 多轮廓检测与筛选
2. 角点排序与透视变换
3. 网格划分与数字提取
4. 结果可视化与保存
数据流分析
整个程序的数据流可以概括为:
输入:数独图像文件路径(如'sudoku2.png')
处理流程:
1. 图像读取与灰度转换
2. 预处理(模糊→阈值→膨胀)
3. 轮廓检测与角点定位
4. 透视变换校正
5. 网格等分与单元格提取
6. 数字区域识别与标准化
7. 结果可视化与保存
输出:
校正后的数独网格图像
分割后的81个单元格图像
拼接的9×9数字大图(带网格编号)
核心算法详解
核心机器视觉方法
(一)图像预处理
高斯模糊(Gaussian Blur)原理:借助高斯核函数对图像进行卷积操作,以此降低图像噪声,平滑图像边缘。
代码体现:cv2.GaussianBlur(proc, (9, 9), 0),通过该操作减少图像中的高频噪声。
自适应阈值分割(Adaptive Thresholding)原理:依据图像局部区域的灰度值差异,动态计算阈值,从而将图像划分为前景和背景。
代码体现:
cv2.adaptiveThreshold(proc,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2),
此操作能有效应对光照不均匀的情况,突出数独的边框和数字区域。
形态学操作(膨胀)原理:利用结构元素(如矩形、十字形)对图像中的前景区域进行扩张,连接邻近的区域。
代码体现:cv2.dilate(proc, kernel),这里使用特定核函数膨胀图像,用于填补数独边框的断裂处,使其轮廓更加完整。
(二)轮廓检测与几何特征分析
轮廓查找(Contour Detection)原理:通过检测图像中灰度值发生剧烈变化的像素点,形成连续的轮廓曲线,以此识别图像中的目标物体。
代码体现:cv2.findContours(processed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE),用于定位数独的外边框轮廓。
轮廓筛选与多边形逼近原理:根据轮廓的面积、顶点数量等特征筛选出符合条件的轮廓(如四边形),并使用多边形逼近轮廓的形状。
代码体现:通过面积排序和顶点数判断(len(approx) == 4)筛选数独边框,再利用cv2.approxPolyDP进行多边形逼近。
角点检测与排序原理:基于轮廓顶点的坐标和几何关系(如坐标和、坐标差),确定四边形的四个角点(左上、右上、右下、左下)。
代码体现:order_points函数通过计算坐标和与坐标差,对轮廓顶点进行排序,得到正确顺序的角点。
(三)透视变换与图像校正
透视变换(Perspective Warping)原理:根据四边形的四个角点,构建透视变换矩阵,将倾斜的数独区域校正为正矩形(正方形),消除透视畸变。
代码体现:cv2.getPerspectiveTransform(src, dst)和cv2.warpPerspective,将数独区域扭曲为规则的正方形,便于后续等分网格。
(四)区域分割与数字提取
网格划分(Grid Inference)原理:将校正后的正方形图像等分为 9×9 的网格,每个网格对应数独的一个单元格。
代码体现:infer_grid函数通过计算边长等分点,生成 81 个单元格的坐标区域。
数字区域提取(Digit Extraction)原理:运用区域生长算法(floodFill)填充数字区域,通过边界框提取数字轮廓,并进行缩放和居中处理,生成标准化的数字图像。
代码体现:find_largest_feature函数通过洪水填充找到数字的主特征区域,scale_and_centre函数将数字缩放并居中到固定尺寸(如 58×58 像素)。
1. 透视变换校正算法
def crop_and_warp(gray, crop_rect):# 1. 确定源点(原始四边形角点)
src = np.array([top_left, top_right, bottom_right, bottom_left], dtype='float32')# 2. 计算目标正方形边长(取四边最大值)
side = max([distance_between(p1, p2) for p1, p2 in pairs])# 3. 定义目标点(正方形四角)
dst = np.array([[0, 0], [side-1, 0], [side-1, side-1], [0, side-1]], dtype='float32')# 4. 计算透视变换矩阵并应用
m = cv2.getPerspectiveTransform(src, dst)
cropped = cv2.warpPerspective(gray, m, (int(side), int(side)))return cropped
数学原理:通过求解3×3透视变换矩阵,将任意四边形映射为标准矩形
关键点:角点顺序必须严格对应(左上→右上→右下→左下)
2. 数字区域提取算法
def extract_digit(bin_img, rect, size):# 1. 裁剪单元格区域
digit = cut_from_rect(bin_img, rect)# 2. 区域生长寻找主特征
flooded, bbox, seed = find_largest_feature(
digit, [margin, margin], [w-margin, h-margin])# 3. 提取边界框内的数字if valid(bbox):
digit = cut_from_rect(flooded, bbox)return scale_and_centre(digit, size, 4)else:return np.zeros((size, size), np.uint8)
核心逻辑:
1. 从网格中裁剪单元格
2. 使用floodFill算法从中心点开始填充数字区域
3. 计算填充区域的边界框
4. 提取边界框内容并标准化
3. 多网格检测算法
def find_sudoku_grids(image_path):# 1. 图像预处理
original = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
processed = pre_process_gray(original)# 2. 轮廓检测与排序
contours, _ = cv2.findContours(processed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)# 3. 筛选四边形轮廓
sudoku_grids = []for contour in contours:
approx = cv2.approxPolyDP(contour, 0.02*cv2.arcLength(contour, True), True)if len(approx) == 4:
sudoku_grids.append(approx)return sudoku_grids
筛选条件:
1. 轮廓面积较大(排序后取前N个)
2. 顶点数为4(近似四边形)
优化方向:可增加长宽比约束和角度约束提高准确性
运行效果
切分结果(黑白效果图为图片增强操作):
脚本评估
设计模式与扩展性
1. 模块化设计
各个功能模块职责单一,通过参数和返回值进行解耦
图像处理流程清晰:预处理→定位→分割→特征提取
2. 扩展性分析
优点:
可通过修改预处理参数适应不同光照条件
可替换数字提取算法(如改用深度学习模型)
多网格处理框架支持批量处理
局限性:
依赖固定网格划分(假设数独为标准9×9)
数字提取依赖简单区域生长,对复杂背景适应性差
缺乏异常处理(如未检测到数独网格的情况)
潜在优化方向
1. 预处理优化:
增加直方图均衡化改善对比度
使用Canny边缘检测替代阈值分割
2. 角点检测优化:
改用Harris角点检测或Shi-Tomasi算法
增加角点验证机制(如角度约束)
3. 数字识别增强:
集成深度学习模型(如MNIST预训练CNN)
增加字符分类后处理(如数独规则验证)
4. 性能优化:
使用Numba或Cython加速计算密集型函数
实现多线程并行处理多个数独网格
5. 鲁棒性提升:
增加网格检测失败的回退策略
实现光照补偿算法适应不同环境
完整代码
import cv2
import operator
import numpy as np
import os
from datetime import datetimedef show_image(img, win='image'):"""显示图片,直到按下任意键继续"""
cv2.imshow(win, img)
cv2.waitKey(0)
cv2.destroyAllWindows()def show_digits(digits, color=255, withBorder=True, grid_num=1):"""将提取并处理过的81个单元格图片构成的列表显示为二维9*9大图"""
rows = []if withBorder:
with_border = [cv2.copyMakeBorder(digit, 1, 1, 1, 1, cv2.BORDER_CONSTANT, None, color) for digit in digits]for i in range(9):if withBorder:
row = np.concatenate(with_border[i * 9: (i + 1) * 9], axis=1)else:
row = np.concatenate(digits[i * 9: (i + 1) * 9], axis=1)
rows.append(row)
bigImage = np.concatenate(rows, axis=0)# 在大图上添加网格编号if grid_num > 1:
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(bigImage, f"Grid {grid_num}", (10, 30), font, 1, (0, 0, 255), 2, cv2.LINE_AA) show_image(bigImage, f'bigImage - Grid {grid_num}')# 生成唯一文件名并保存
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"segmentedBigImg_grid{grid_num}_{timestamp}.jpg"
cv2.imwrite(filename, bigImage)print(f"已保存数独网格 {grid_num} 到: {filename}")def convert_with_color(color, img):"""如果color是元组且img是灰度图,则动态地转换img为彩图"""if len(color) == 3 and (img.ndim == 2 or (img.ndim == 3 and img.shape[2] == 1)):
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)return imgdef pre_process_gray(gray, skip_dilate=False):"""使用高斯模糊、自适应阈值分割和/或膨胀来暴露图像的主特征"""
proc = cv2.GaussianBlur(gray.copy(), (9, 9), 0)
proc = cv2.adaptiveThreshold(proc, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)if not skip_dilate:
kernel = np.array([[0., 1., 0.], [1., 1., 1.], [0., 1., 0.]], np.uint8)
proc = cv2.dilate(proc, kernel)return procdef display_points(in_img, points, radius=5, color=(0, 0, 255)):"""在图像上绘制彩色圆点,原图像可能是灰度图"""
img = in_img.copy()
img = convert_with_color(color, img)for point in points:
cv2.circle(img, tuple(int(x) for x in point), radius, color, -1)return imgdef find_corners_of_largest_polygon(bin_img):"""找出图像中面积最大轮廓的4个角点。"""
contours, h = cv2.findContours(bin_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)
polygon = contours[0] bottom_right_idx, _ = max(enumerate([pt[0][0] + pt[0][1] for pt in polygon]), key=operator.itemgetter(1))
top_left_idx, _ = min(enumerate([pt[0][0] + pt[0][1] for pt in polygon]), key=operator.itemgetter(1))
bottom_left_idx, _ = min(enumerate([pt[0][0] - pt[0][1] for pt in polygon]), key=operator.itemgetter(1))
top_right_idx, _ = max(enumerate([pt[0][0] - pt[0][1] for pt in polygon]), key=operator.itemgetter(1)) points = [polygon[top_left_idx][0], polygon[top_right_idx][0],
polygon[bottom_right_idx][0], polygon[bottom_left_idx][0]]
show_image(display_points(bin_img, points), '4-points')return pointsdef distance_between(p1, p2):"""返回两点之间的标量距离"""
a = p2[0] - p1[0]
b = p2[1] - p1[1]return np.sqrt((a ** 2) + (b ** 2))def crop_and_warp(gray, crop_rect):"""将灰度图像中由4角点围成的四边形区域裁剪出来,并将其扭曲为类似大小的正方形"""
top_left, top_right, bottom_right, bottom_left = crop_rect[0], crop_rect[1], crop_rect[2], crop_rect[3]
src = np.array([top_left, top_right, bottom_right, bottom_left], dtype='float32') side = max([
distance_between(bottom_right, top_right),
distance_between(top_left, bottom_left),
distance_between(bottom_right, bottom_left),
distance_between(top_left, top_right)]) dst = np.array([[0, 0], [side - 1, 0], [side - 1, side - 1], [0, side - 1]], dtype='float32')
m = cv2.getPerspectiveTransform(src, dst)
cropped = cv2.warpPerspective(gray, m, (int(side), int(side)))# 生成唯一文件名并保存
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"cropped_grid_{timestamp}.png"
cv2.imwrite(filename, cropped)print(f"已保存裁剪图像到: {filename}") show_image(cropped, 'cropped')return croppeddef infer_grid(square_gray):"""从正方形灰度图像推断其内部81个单元网格的位置(以等分方式)。"""
squares = []
side = square_gray.shape[:1][0] / 9for j in range(9):for i in range(9):
p1 = (i * side, j * side)
p2 = ((i + 1) * side, (j + 1) * side)
squares.append((p1, p2))return squaresdef cut_from_rect(img, rect):"""从图像中切出一个矩形ROI区域。"""return img[int(rect[0][1]):int(rect[1][1]), int(rect[0][0]):int(rect[1][0])]def scale_and_centre(img, size, margin=0, background=0):"""把单元格图片img经缩放且加边距,置于边长为size的新背景正方形图像中"""
h, w = img.shape[:2]def centre_pad(length):
padAll = size - lengthif padAll % 2 == 0:
pad1 = int(padAll / 2)
pad2 = pad1else:
pad1 = int(padAll / 2)
pad2 = pad1 + 1return pad1, pad2def scale(r, x):return int(r * x)if h > w:
t_pad = int(margin / 2)
b_pad = t_pad
ratio = (size - margin) / h
w, h = scale(ratio, w), scale(ratio, h)
l_pad, r_pad = centre_pad(w)else:
l_pad = int(margin / 2)
r_pad = l_pad
ratio = (size - margin) / w
w, h = scale(ratio, w), scale(ratio, h)
t_pad, b_pad = centre_pad(h) img = cv2.resize(img, (w, h))
img = cv2.copyMakeBorder(img, t_pad, b_pad, l_pad, r_pad, cv2.BORDER_CONSTANT, None, background)if margin % 2 != 0:
img = cv2.resize(img, (size, size))return imgdef find_largest_feature(inp_img, scan_tl, scan_br):"""利用floodFill函数返回它所填充区域的边界框的事实,找到图像中的主特征,将此结构填充为白色,其余部分降为黑色。"""
img = inp_img.copy()
h, w = img.shape[:2]
max_area = 0
seed_point = (None, None)for x in range(scan_tl[0], scan_br[0]):for y in range(scan_tl[1], scan_br[1]):if img.item(y, x) == 255 and x < w and y < h:
area = cv2.floodFill(img, None, (x, y), 64)if area[0] > max_area:
max_area = area[0]
seed_point = (x, y)for x in range(w):for y in range(h):if img.item(y, x) == 255 and x < w and y < h:
cv2.floodFill(img, None, (x, y), 64)if all([p is not None for p in seed_point]):
cv2.floodFill(img, None, seed_point, 255)
top, bottom, left, right = h, 0, w, 0for x in range(w):for y in range(h):if img.item(y, x) == 64:
cv2.floodFill(img, None, (x, y), 0)if img.item(y, x) == 255:
top = y if y < top else top
bottom = y if y > bottom else bottom
left = x if x < left else left
right = x if x > right else right bbox = [[left, top], [right, bottom]]return img, np.array(bbox, dtype='float32'), seed_pointdef extract_digit(bin_img, rect, size):"""从预处理后的二值方形大格子图中提取由rect指定的小单元格数字图"""
digit = cut_from_rect(bin_img, rect)
h, w = digit.shape[:2]
margin = int(np.mean([h, w]) / 2.5)
flooded, bbox, seed = find_largest_feature(digit, [margin, margin], [w - margin, h - margin]) w = bbox[1][0] - bbox[0][0]
h = bbox[1][1] - bbox[0][1]if w > 0 and h > 0 and (w * h) > 200:
digit = cut_from_rect(flooded, bbox)return scale_and_centre(digit, size, 4)else:return np.zeros((size, size), np.uint8)def get_digits(square_gray, squares, size):"""提取小单元格数字,组织成数组形式"""
digits = []
square_bin = pre_process_gray(square_gray.copy(), skip_dilate=True) color = convert_with_color((0, 0, 255), square_bin)
h, w = color.shape[:2]for i in range(10):
cv2.line(color, (0, int(i * h / 9)), (w - 1, int(i * h / 9)), (0, 0, 255))
cv2.line(color, (int(i * w / 9), 0), (int(i * w / 9), h - 1), (0, 0, 255))
show_image(color, 'drawRedLine')for square in squares:
digits.append(extract_digit(square_bin, square, size))return digitsdef find_sudoku_grids(image_path):"""定位图像中的所有数独图"""
original = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
processed = pre_process_gray(original)# 查找轮廓
contours, _ = cv2.findContours(processed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)# 筛选可能是数独图的轮廓(假设数独图是较大的矩形)
sudoku_grids = []for contour in contours:
epsilon = 0.02 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)if len(approx) == 4: # 矩形
sudoku_grids.append(approx)return sudoku_gridsdef parse_multiple_grids(image_path):"""处理包含多个数独图的图像"""
sudoku_grids = find_sudoku_grids(image_path)
original = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)for i, grid in enumerate(sudoku_grids):print(f"Processing grid {i + 1}")
corners = grid.reshape(4, 2) # 四个角点# 确保角点顺序正确(左上、右上、右下、左下)
corners = order_points(corners)
cropped = crop_and_warp(original, corners)
squares = infer_grid(cropped)
digits = get_digits(cropped, squares, 58)
show_digits(digits, withBorder=True, grid_num=i+1)def order_points(pts):"""将四个角点按左上、右上、右下、左下顺序排列"""
rect = np.zeros((4, 2), dtype="float32")
s = pts.sum(axis=1)
rect[0] = pts[np.argmin(s)] # 左上
rect[2] = pts[np.argmax(s)] # 右下
diff = np.diff(pts, axis=1)
rect[1] = pts[np.argmin(diff)] # 右上
rect[3] = pts[np.argmax(diff)] # 左下return rectif __name__ == '__main__':
image_path = 'sudoku2.png'
parse_multiple_grids(image_path)
延伸用途
(一)表格识别与数据提取
应用场景:可用于答题卡识别、财务报表数字提取、手写表格内容分析等。
技术迁移:利用类似的轮廓检测和透视校正方法定位表格区域,再通过网格划分提取单元格内容,结合 OCR 技术识别文字或数字。
(二)工业检测与质量控制
应用场景:零件尺寸测量、缺陷检测(如孔洞、边缘破损)、装配完整性检查等。
技术迁移:通过轮廓分析提取零件轮廓,与标准模板对比检测缺陷;利用透视变换校正零件图像,实现高精度尺寸测量。
(三)文档图像处理
应用场景:扫描文档矫正(如弯曲页面展平)、发票 / 证件信息提取、多语言文字区域分割。
技术迁移:使用透视变换校正扫描文档的倾斜或透视畸变,结合形态学操作和轮廓检测分割文本区域,为 OCR 预处理提供高质量图像。
(四)智能安防与监控
应用场景:车牌识别(LPR)、人流量统计(通过轮廓跟踪)、异常行为检测(如遗留物品检测)。
技术迁移:通过轮廓检测定位车牌区域,结合透视变换校正车牌图像,再提取字符区域进行识别;利用轮廓跟踪算法分析监控视频中的目标运动轨迹。
(五)教育与娱乐领域
应用场景:数学作业自动批改(识别手写数字和公式)、棋盘游戏 AI(如围棋、象棋的棋盘识别)、AR/VR 互动(如手势识别中的轮廓跟踪)。
技术迁移:对数独代码中的网格分割和特征提取方法进行调整,以适应棋盘格子或手写字符的检测,结合机器学习模型实现自动评分或游戏逻辑。
(六)医学图像处理
应用场景:细胞形态分析(轮廓检测与特征提取)、显微图像分割(如组织切片中的区域划分)。
技术迁移:利用形态学操作和区域生长算法分割医学图像中的目标区域(如细胞、肿瘤),结合几何特征分析辅助疾病诊断。
相关文章:

机器学习方法实现数独矩阵识别器
目录 导包 工具函数构建说明 1. 基础图像处理工具 2. 图像预处理模块 3. 数独轮廓检测与定位 4. 网格划分与单元格提取 5. 数字特征提取 6. 多网格处理流程 数据流分析 核心算法详解 核心机器视觉方法 1. 透视变换校正算法 2. 数字区域提取算法 3. 多网格检测算法…...
OpenEuler服务器警告邮件自动化发送:原理、配置与安全实践
OpenEuler服务器警告邮件自动化发送:原理、配置与安全实践 在服务器的运维管理过程中,及时感知系统异常状态至关重要。当OpenEuler系统运行时,将服务器的警告信息实时推送至邮箱,能帮助运维人员快速响应潜在问题,保障…...
随机访问介质访问控制:网络中的“自由竞争”艺术
想象一场自由辩论赛——任何人随时可以发言,但可能多人同时开口导致混乱。这正是计算机网络中随机访问协议的核心挑战:如何让多个设备在共享信道中高效竞争?本文将深入解析五大随机访问技术及其智慧。 一、核心思想:自由竞争 冲突…...
【Redis】笔记|第9节|Redis Stack扩展功能
Redis Stack 扩展功能笔记(基于 Redis 7) 一、Redis Stack 概述 定位:Redis OSS 扩展模块(JSON、搜索、布隆过滤器等),提供高级数据处理能力。核心模块: RedisJSON:原生 JSON 支持…...

【Vmwrae】快速安装windows虚拟机
前言 虚拟机是我们在使用电脑进行开发或者平常工作时经常使用到的工具 它可以自定义各种硬件,运行各种不同的系统,且无论发生什么都不会影响到实体机。 教程主要讲了如何在零基础的情况下快速安装一台虚拟机。 下载安装 VMware Workstation Pro17 …...

多线程3(Thread)
wait / notify 线程调度是随机的,但是我们可以使用wait/notify进行规划。 join是控制线程结束顺序,而wait/notify是控制详细的代码块,例如: 线程1执行完一段代码,让线程2继续执行,此时线程2就通过wait进…...

附加模块--Qt Shader Tools功能及架构解析
Qt 6.0 引入了全新的 Shader Tools 模块,为着色器管理提供了现代化、跨平台的解决方案。 一、主要功能 核心功能 跨平台着色器编译 支持 GLSL、HLSL 和 MetalSL 着色器语言 可在运行时或构建时进行着色器编译 自动处理不同图形API的着色器变体 SPIR-V 支持 能…...
ffmpeg(五):裁剪与合并命令
裁剪(剪切) 精准裁剪(有转码,支持任意起止时间) # 从第 10 秒到第 30 秒,重新编码 ffmpeg -i input.mp4 -ss 00:00:10 -to 00:00:30 -c:v libx264 -c:a aac output.mp4快速裁剪(无转码&#x…...
CCPC guangdongjiangsu 2025 F
题目链接:https://codeforces.com/gym/105945/problem/F 题目背景: 你知道自己队伍的过题数、罚时,还知道另一个队伍的每次提交记录(三种状态:ac:通过,rj:未通过,pb&…...
SSE (Server-Sent Events) 技术简介
一、SSE 技术概述 Server-Sent Events (SSE) 是一种允许服务器向客户端实时推送数据的 Web 技术,它基于 HTTP 协议实现服务器到客户端的单向通信。 基本特点 ● 单向通信:仅服务器→客户端方向 ● 基于HTTP:使用标准HTTP协议,无需…...

网络编程(计算机网络基础)
思维导图 认识网络 1.网络发展史 ARPnetA(阿帕网)->internet(因特网)->移动互联网->物联网 2.局域网与广域网 局域网 概念:的缩写是LAN(local area network),顾名思义,是个本地的网络,只能实现…...
常见 DOM 事件全解析
常见 DOM 事件全解析 DOM 事件是用户与网页交互的核心机制,分为 用户交互事件、文档加载事件、表单事件、键盘事件 等 8 大类: 一、鼠标事件 事件触发时机典型应用场景click点击元素(按下+释放)按钮操作、导航跳转dblclick双击元素文件/图片编辑mousedown鼠标按下拖拽开始…...

在React 中安装和配置 shadcn/ui
1. 创建 React 项目 pnpm create vitelatest .选择模板:React TypeScript安装依赖:pnpm install2. 添加 Tailwind CSS pnpm add -D tailwindcss postcss autoprefixer修改 src/index.css 内容: import "tailwindcss";3. 配置 T…...

WINUI——WINUI开发中谨慎使用x:Bind
原因——为什么需要谨慎使用x:Bind? 在实际开发中发现,使用它会导致VM回收不及时,可能导致内存泄漏。 那为何要在项目中使用它呢? 因为:{x:Bind} 标记扩展(Windows 10 的新增功能)…...

MSYS2 环境配置与 Python 项目依赖管理笔记
#工作记录 MSYS2 环境配置 安装和更新 MSYS2 初始安装 下载并安装 MSYS2: 访问 MSYS2 官方网站 并下载安装包。 按照安装向导完成安装。 更新 MSYS2: 打开 MSYS2 终端(MSYS2 MINGW64)。 更新包数据库和核心系统包࿱…...
Elasticsearch:spring2.x集成elasticsearch8.x
相关安装就不介绍了直接代码集成 <!-- elasticsearch版本需要和你安装的版本一致 --><properties><elasticsearch.version>8.11.1</elasticsearch.version><jakarta-json.version>2.1.2</jakarta-json.version><logstash.version>7…...

华为云Flexus+DeepSeek征文|华为云一键部署知识库搜索增强版Dify平台,构建智能聊天助手实战指南
目录 前言 1 架构描述 2 资源栈创建流程详解 2.1 选择部署模板 2.2 参数配置内容 2.3 资源栈设置选项 2.4 配置确认与执行方式 3 部署过程与控制台反馈 3.1 实时资源监控 3.2 资源详情与访问路径 3.3 模板与事件管理 4 知识库构建流程 4.1 数据导入操作 4.2 文本…...
gem5-gpu教程 在gem5-gpu上运行多个应用程序
问题一、gem5-gpu是否能够在系统调用仿真中同时运行两个不同的应用程序,一个在CPU上,另一个在gpu上。如果是这样,我该怎么做?我查看了配置和帮助文件,没有找到明确的方法。看起来rodinia基准测试使用CPU在GPU内核中启动工作,CPU内核在GPU执行时几乎处于空闲状态。这里的另…...

分形几何在医学可视化中的应用:从理论到Python实战
分形几何在医学可视化中的应用:从理论到Python实战 前言 分形几何作为描述自然界复杂结构的数学工具,正通过其自相似性和分数维度特性,革新医学影像分析领域。本文系统阐述分形几何在医学影像中的创新应用,涵盖从图像预处理、分…...
四自由度机械臂Simulink仿真设计与实现
四自由度机械臂Simulink仿真设计与实现 摘要 本文详细介绍了基于MATLAB/Simulink的四自由度机械臂建模、仿真与控制实现。通过建立完整的运动学和动力学模型,设计PID控制器,实现轨迹跟踪功能,并利用3D可视化技术进行仿真验证。全文涵盖理论建模、Simulink实现和仿真分析三…...

ESP-Brookesia:融合 AI 大模型,全新一代 GUI 开发与管理平台
乐鑫信息科技 (688018.SH) 推出 ESP-Brookesia ——一款专为物联网设备打造、集成 AI 交互能力的 UI 开发与管理框架。 ESP-Brookesia 深度融合 AI 大模型技术,为智能屏显应用赋予语音识别、自然语言对话、拟人化反馈等能力,帮助开发者构建更智能、更具…...

【MATLAB去噪算法】基于CEEMD联合小波阈值去噪算法(第三期)
02.去噪算法原理 1.引言 传统EMD方法存在模态混叠问题,即信号成分在不同IMF分量中出现碎片化分布。为改进这一问题,Huang等(1999)提出间歇性测试算法,但效果有限。Wu和Huang(2009)发展的集合经…...

机器学习实战37-基于情感字典和机器学习的股市舆情分析可视化系统
文章目录 一、项目背景数字时代情感分析情况二、项目流程1.数据采集与预处理2.复合情感分析模型构建3.舆情分析可视化:三、机器学习算法原理1.支持向量机基础2.核函数与高维映射3.情感分类特征融合4.模型训练与优化四、实现代码五、系统特点与优势1.复合情感分析模型2.多维度可…...
【2025CVPR】模型融合新范式:PLeaS算法详解(基于排列与最小二乘的模型合并技术)
本文深入解析ICLR 2025顶会论文《PLeaS: Merging Models with Permutations and Least Squares》,揭示模型融合领域突破性进展. 一、问题背景:模型合并的核心挑战 随着开源模型的爆发式增长,如何高效合并多个专用模型成为关键挑战。传统方法存在三大痛点: 初始化依赖…...

CAD多面体密堆积3D插件
插件介绍 CAD多面体密堆积3D插件可在AutoCAD内建立三维随机多面体密堆积模型。 插件内置物理动力学模拟算法,通过模拟重力、碰撞等现象,使多面体在虚拟环境中发生自然堆积,进而实现真实的堆积效果。多面体堆积模拟中存在的局部穿模问题可通…...

LLMs 系列科普文(5)
在前文中,我们讲述了什么是基础模型,并重点以 LLaMA 3.1 基础模型为例,向大家演示了它可以做什么,有哪些问题或有趣的现象。 在进入新的主题内容之前,我们再次对 基础模型 做一些总结: 这是一个基于 toke…...

HarmonyOS开发:显示图片功能详解
目录 前言 Image组件基础 1、Image组件概述 2、加载图片资源 3、存档图类型数据源 (1)本地资源 (2)网络资源 (3)Resource资源 (4)媒体库file://data/storage (…...

ORACLE 修改端口号之后无法启动?
Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生。这一问题通常源于配置错误或环境冲突,而非端口修改本身。以下是系统性解决方案: 🔍 一、问题根源分析 配置文件语法错误 修…...
Qt Quick Test模块功能及架构
Qt Quick Test 是专门为测试 QML 应用程序设计的模块,在 Qt 6.0 中得到了显著增强。 一、主要功能/使用方法 核心功能概述 QML 单元测试框架 提供完整的 QML 测试环境 支持测试用例组织和执行 包含 QML 断言函数和测试结果收集 测试类型支持 组件功能测试 用…...

Excel自动分列开票工具推荐
软件介绍 本文介绍一款基于Excel VBA开发的自动分列开票工具,可高效处理客户对账单并生成符合要求的发票清单。 软件功能概述 该工具能够将客户对账单按照订单号自动拆分为独立文件,并生成可直接导入发票清单系统的标准化格式。 软件特点 这是一款体…...