OpenCV练习(2)图像校正

  • 1、傅里叶变换 + 霍夫变换+ 直线 + 角度 + 旋转
  • 2、边缘检测 + 霍夫变换 + 直线+角度 + 旋转
  • 3、四点透视 + 角度 + 旋转
  • 4、检测矩形轮廓 + 角度 + 旋转

1.目的

实现类似全能扫面王的图像校正功能

2. 基于轮廓提取和透射变换

基于轮廓提取和透射变换的矫正算法更适用于车牌身份证人民币书本、 发票一类矩形形状而且边界明显的物体矫正。所校正的内容必须要有清晰的完整轮廓。

基本步骤:

  1. 图片灰度化
  2. 二值化/canny边缘检测等操作
  3. 检测轮廓,并筛选出目标轮廓(通过横纵比或面积去除干扰轮廓)
  4. 获取图像顶点
  5. 透视变换

代码:

import cv2
import numpy as npdef contour_to_rect(contour):pts = contour.reshape(4, 2)print(pts)rect = np.zeros((4, 2), dtype = "float32")# top-left point has the smallest sum# bottom-right has the largest sums = pts.sum(axis = 1)
#     print(s)rect[0] = pts[np.argmin(s)]
#     print(pts[np.argmin(s)])rect[2] = pts[np.argmax(s)]# compute the difference between the points:# the top-right will have the minumum difference# the bottom-left will have the maximum differencediff = np.diff(pts, axis = 1)rect[1] = pts[np.argmin(diff)]rect[3] = pts[np.argmax(diff)]return rect# approximate the contour by a more primitive polygon shape
def approximate_contour(contour):peri = cv2.arcLength(contour, True)return cv2.approxPolyDP(contour, 0.032 * peri, True)# 获取顶点坐标
def get_receipt_contour(contours):# loop over the contoursfor c in contours:approx = approximate_contour(c)# if our approximated contour has four points, we can assume it is receipt's rectangleif len(approx) == 4:return approxdef wrap_perspective(img, rect):# unpack rectangle points: top left, top right, bottom right, bottom left(tl, tr, br, bl) = rect# compute the width of the new imagewidthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))# compute the height of the new imageheightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))# take the maximum of the width and height values to reach# our final dimensionsmaxWidth = max(int(widthA), int(widthB))maxHeight = max(int(heightA), int(heightB))# destination points which will be used to map the screen to a "scanned" viewdst = np.array([[0, 0],[maxWidth - 1, 0],[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = "float32")# calculate the perspective transform matrixM = cv2.getPerspectiveTransform(rect, dst)# warp the perspective to grab the screenreturn cv2.warpPerspective(img, M, (maxWidth, maxHeight))if __name__ == "__main__":img = cv2.imread("./images/1.png")gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 用高斯滤波处理原图像降噪blur = cv2.GaussianBlur(gray, (5, 5), 0)#canny边缘检测(仅针对这次的输入图片)edged = cv2.Canny(blur, 50, 150)contours, h = cv2.findContours(edged.copy(), mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)# img_contours = cv2.drawContours(img.copy(), contours, -1, (0, 0, 255), 3)largest_contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5]# img_largest_contours = cv2.drawContours( img.copy(), largest_contours, -1, (0, 0, 255), 3)receipt_contour = get_receipt_contour(largest_contours)# img_receipt_contour = cv2.drawContours(img.copy(), [receipt_contour], -1, (0, 0, 255), 3)ori_img = img.copy()for coor in contour_to_rect(receipt_contour):cv2.circle(ori_img, (int(coor[0]), int(coor[1])), 1, (0, 0, 255), 4)# 进行透视变换scanned = wrap_perspective(img.copy(), contour_to_rect(receipt_contour))
2.1 图像灰度化 

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

blur = cv2.GaussianBlur(gray, (5, 5), 0)(如果有噪声可以加个高斯滤波)

2.2 canny边缘检测

edged = cv2.Canny(blur, 50, 150) (三个参数分别输入图像,最小阈值,最大阈值)

下图中左为输出,右为边缘检测结果。看起来效果还行

左为所有轮廓绘制,右为面积前五的绘制。可以看到,书中长方形的框并不在检测中,这是因为在进行边缘检测时色差不大导致没检测出来,后续使用闭运算处理将连断出填充完。

 

 但是对于,图像边框,或者说前景与背景色差不大时,很难检测出来,如下图放在白色桌面的安装指南

 

2.3 检测轮廓,并筛选出目标轮廓(通过横纵比或面积去除干扰轮廓) 

 contours, h = cv2.findContours(edged.copy(), mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
  img_contours = cv2.drawContours(img.copy(), contours, -1, (0, 0, 255), 3)

检测图像轮廓并绘制所有的轮廓

# approximate the contour by a more primitive polygon shape
def approximate_contour(contour):
    peri = cv2.arcLength(contour, True)
    return cv2.approxPolyDP(contour, 0.032 * peri, True)

# 获取顶点坐标
def get_receipt_contour(contours):
    # loop over the contours
    for c in contours:
        approx = approximate_contour(c)
        # if our approximated contour has four points, we can assume it is receipt's rectangle
        if len(approx) == 4:
            return approx

在这个实现中,approximate_contour函数使用cv2.approxPolyDP来近似轮廓。cv2.approxPolyDP的第二个参数是精度参数,它是一个距离值,表示近似轮廓与原始轮廓之间的最大距离。这个值是原始轮廓周长的百分比,通常设置为一个很小的值(例如0.02)。第三个参数True表示近似出的多边形是闭合的。

get_receipt_contour函数然后使用这个近似函数来寻找一个四边形的轮廓,假设这个四边形是收据的形状。如果找到了一个有四个顶点的轮廓,它就返回这个轮廓。如果没有找到,函数将返回None

请注意,这个函数假设收据是一个四边形,并且是轮廓列表中面积最大的四边形。在实际应用中,可能需要根据收据的具体形状和图像中的其他元素来调整这个函数。

 2.4 获取图像顶点            

    receipt_contour = get_receipt_contour(largest_contours)
    img_receipt_contour = cv2.drawContours(img.copy(), [receipt_contour], -1, (0, 0, 255), 3)

def contour_to_rect(contour):
    pts = contour.reshape(4, 2)
    print(pts)
    rect = np.zeros((4, 2), dtype = "float32")
    # top-left point has the smallest sum
    # bottom-right has the largest sum
    s = pts.sum(axis = 1)
#     print(s)
    rect[0] = pts[np.argmin(s)]
#     print(pts[np.argmin(s)])
    rect[2] = pts[np.argmax(s)]
    # compute the difference between the points:
    # the top-right will have the minumum difference
    # the bottom-left will have the maximum difference
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

在您提供的contour_to_rect函数中,目标是将以四个顶点形式给出的轮廓转换为一个矩形,这个矩形以特定的顺序排列顶点,通常是顺时针或逆时针方向,从左上角开始。然而,在您提供的代码中存在一些问题,包括一个拼写错误和一个可能的逻辑错误。我将为您纠正这些问题,并提供一个完整的函数,该函数将返回一个按正确顺序排列顶点的矩形。

ori_img = img.copy() for coor in contour_to_rect(receipt_contour): cv2.circle(ori_img, (int(coor[0]), int(coor[1])), 1, (0, 0, 255), 4) 

将筛选的四个点在图像中标注

 

2.5 透视变换

scanned = wrap_perspective(img.copy(), contour_to_rect(receipt_contour))
def wrap_perspective(img, rect):# unpack rectangle points: top left, top right, bottom right, bottom left(tl, tr, br, bl) = rect# compute the width of the new imagewidthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))# compute the height of the new imageheightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))# take the maximum of the width and height values to reach# our final dimensionsmaxWidth = max(int(widthA), int(widthB))maxHeight = max(int(heightA), int(heightB))# destination points which will be used to map the screen to a "scanned" viewdst = np.array([[0, 0],[maxWidth - 1, 0],[maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = "float32")# calculate the perspective transform matrixM = cv2.getPerspectiveTransform(rect, dst)# warp the perspective to grab the screenreturn cv2.warpPerspective(img, M, (maxWidth, maxHeight))

 

您提供的wrap_perspective函数是用于执行透视变换的,这种变换通常用于将图像中的四边形区域(如收据、文档等)转换为俯视图,即“扫描”视图。这个函数接受两个参数:要变换的图像img和一个表示四边形顶点的numpy数组rect

以下是函数中每一步的解释:

  1. 解包四边形顶点:将四边形的顶点解包为tl(左上角)、tr(右上角)、br(右下角)和bl(左下角)。

  2. 计算新图像的宽度:通过计算对角线brbltrtl的距离来得到新图像的潜在宽度。使用欧几里得距离公式sqrt((x2 - x1)^2 + (y2 - y1)^2)

  3. 计算新图像的高度:同样,通过计算对角线trbrtlbl的距离来得到新图像的潜在高度。

  4. 确定最终尺寸:通过取宽度 和高度的最大值来确保四边形在变换后不会被裁剪。

  5. 定义目标点:创建一个目标点数组dst,这些点定义了变换后的四边形的顶点位置。这些点将图像映射到一个矩形的“扫描”视图。

  6. 计算透视变换矩阵:使用cv2.getPerspectiveTransform函数计算从原始四边形到目标矩形的透视变换矩阵M

  7. 执行透视变换:使用cv2.warpPerspective函数应用透视变换到图像img上,得到变换后的图像。

 

3. 基于霍夫直线探测和仿射变换

基于霍夫直线探测的矫正算法更适用于文本类等无明显边界图像的矫正。图像画面必须要干净

算法步骤

  1. 霍夫线变换探测出图像中的所有直线。
  2. 计算出每条直线的倾斜角,求他们的平均值。
  3. 根据倾斜角旋转矫正。
  4. 最后根据文本尺寸裁剪图片。

代码:

import cv2
import numpy as npimg = cv2.imread("./images/4.jpg")
src = img.copy()
gray = cv2.cvtColor(src, cv2.COLOR_RGB2GRAY);
edged = cv2.Canny(src, 50, 200, apertureSize=3);# 第5个参数就是阈值,阈值越大,检测精度越高
plines = cv2.HoughLines(edged, 1, np.pi / 180, 200);
if plines is not None:plines = plines.reshape(-1, 2)print(len(plines), "lines detected")sum_theta = 0.0for rho, theta in plines:# rho, theta = line[0]a = np.cos(theta)b = np.sin(theta)x0 = a * rhoy0 = b * rhox1 = int(x0 + 1000*(-b))y1 = int(y0 + 1000*(a))x2 = int(x0 - 1000*(-b))y2 = int(y0 - 1000*(a))sum_theta += theta# 绘制直线cv2.line(src, (x1, y1), (x2, y2), (0, 0, 255), 2)# 计算平均角度
average_theta = sum_theta / len(plines)
angle = np.degrees(average_theta) - 90# 计算旋转中心
center = (float(img.shape[1] / 2.0), float(img.shape[0] / 2.0))
# 计算对角线长度作为旋转后图像的尺寸
length = int(np.sqrt(img.shape[0]**2 + img.shape[1]**2))
# 计算旋转矩阵
M = cv2.getRotationMatrix2D(center, angle, 1)
# 进行仿射变换并填充背景色为白色
src_rotate = cv2.warpAffine(img, M, (length, length), borderValue=(255, 255, 255))
3.1 图像预处理

在此不赘述,根据实际情况来

3.2 霍夫线变换

# 第5个参数就是阈值,阈值越大,检测精度越高
plines = cv2.HoughLines(edged, 1, np.pi / 180, 200);

在OpenCV中,cv2.HoughLines函数用于检测图像中的直线。它使用霍夫变换(Hough Transform)来找到图像中直线的参数,然后将这些参数转换为图像中的直线。

您提供的代码片段plines = cv2.HoughLines(edged, 1, np.pi / 180, 200);是使用霍夫变换在经过Canny边缘检测的图像edged中检测直线的例子。

这里的参数解释如下:

  • edged:这是已经通过Canny边缘检测得到的图像。
  • 1:这是霍夫变换中使用的rho(极径)参数。它定义了检测直线时的搜索范围。较大的值会使检测到的直线更加稀疏,而较小的值则可能导致检测到的直线更加密集。
  • np.pi / 180:这是霍夫变换中使用的theta(角度)参数。它定义了检测直线时的角度范围。这里使用的是单位圆上的角度,即0到π弧度。
  • 200:这是霍夫变换中使用的阈值参数。它定义了直线检测的灵敏度。较大的值会使检测到的直线更加稀疏,而较小的值则可能导致检测到的直线更加密集。


if plines is not None:
    plines = plines.reshape(-1, 2)
    print(len(plines), "lines detected")

在OpenCV中,cv2.HoughLines函数返回一个包含检测到的直线的数组,如果没有任何直线被检测到,这个数组将为None。这种情况可能发生在以下几种情况下:

  1. 图像噪声:如果图像中的噪声非常强烈,可能会导致无法检测到任何直线。

  2. 参数设置cv2.HoughLines函数的参数设置(如阈值、角度范围等)可能不适合当前图像。如果参数设置不当,可能无法检测到任何直线。

  3. 图像内容:如果图像中没有明显的直线结构,例如在复杂的自然场景中,可能会检测不到直线。

  4. 图像大小:如果图像非常小,可能没有足够的空间来检测直线。

  5. 图像分辨率:如果图像的分辨率非常低,可能会导致检测到的直线不够精确。

  6. 图像方向:如果图像的方向与霍夫变换的搜索方向不匹配,可能会检测不到直线。

在实际应用中,您可能需要根据图像的具体内容和噪声水平来调整cv2.HoughLines函数的参数,以提高检测直线的效果。

    sum_theta = 0.0
    for rho, theta in plines:
        # rho, theta = line[0]
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a * rho
        y0 = b * rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))
        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))
        sum_theta += theta
        # 绘制直线
        cv2.line(src, (x1, y1), (x2, y2), (0, 0, 255), 2)

在您提供的代码片段中,您正在遍历通过霍夫变换检测到的直线,并将这些直线绘制在原始图像src上。每个直线由两个点定义,这两个点是根据极径rho和角度theta计算出来的。

代码中的关键步骤如下:

  1. 遍历plines数组,其中每个元素是一个包含两个值rhotheta的元组。rho是直线与原点之间的距离,而theta是从x轴正向到直线方向的角度(以弧度为单位)。

  2. 对于每个元素,您首先提取rhotheta值。

  3. 使用np.cos(theta)np.sin(theta)计算直线斜率ab

  4. 使用a * rhob * rho计算直线上的两个点的x和y坐标。这些坐标是通过将rho值乘以直线的方向向量(由ab定义)得到的。

  5. 使用int(x0 + 1000*(-b))int(y0 + 1000*(a))计算第一个点的坐标,其中1000是一个常数,用于确保坐标在图像范围内。

  6. 使用int(x0 - 1000*(-b))int(y0 - 1000*(a))计算第二个点的坐标。

  7. 使用cv2.line函数在原始图像src上绘制从第一个点到第二个点的直线,颜色为红色,线宽为2。

  8. 将角度theta累加到变量sum_theta中。

 

经过自己的多次实验,发现霍夫线变换的弧度转化为角度时,是以Y轴正半轴为0°,顺时针计算角度。并且在仿射变换进行旋转时,如果给的是正数,就会逆时针旋转,如果给的是负数,就会顺时针旋转 

 

3.3 旋转角度和旋转中心

# 计算平均角度
average_theta = sum_theta / len(plines)
angle = np.degrees(average_theta) - 90

在OpenCV中,cv2.HoughLines函数返回的角度参数是以弧度为单位的。这个函数使用霍夫变换来检测图像中的直线,而霍夫变换中使用的角度参数是弧度制的。

霍夫变换是一种在图像中检测直线的方法,它将图像中的每个点转换为一个参数空间中的一个点,其中参数空间是一个笛卡尔坐标系,x轴和y轴分别对应于图像中的直线的斜率和截距。在霍夫变换中,θ是直线的倾斜角,以弧度为单位。

因此,当您从cv2.HoughLines函数中获取θ值时,这些值是以弧度为单位的。如果您需要将它们转换为角度,可以使用NumPy的np.degrees函数来进行转换。

请注意,弧度与度的转换关系是:

1 弧度=180​ /Π 度

# 计算旋转中心
center = (float(img.shape[1] / 2.0), float(img.shape[0] / 2.0))
# 计算对角线长度作为旋转后图像的尺寸
length = int(np.sqrt(img.shape[0]**2 + img.shape[1]**2))

3.4 旋转矩阵

# 计算旋转矩阵

M = cv2.getRotationMatrix2D(center, angle, 1)

3.5 仿射变换

# 进行仿射变换并填充背景色为白色

src_rotate = cv2.warpAffine(img, M, (length, length), borderValue=(255, 255, 255))

 

4. 基于最小外接矩形和仿射变换

有明显的单一外接矩形的图像,最好是文本。

算法步骤:

  1. 灰度化以及预处理
  2. 二值化/边缘检测
  3. 最小外接矩形
  4. 旋转中心、旋转角度以及旋转矩阵
  5. 仿射变换

代码:

import numpy as np
import cv2 as cvdef binary(img):gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)return binarydef  Transformation(img,src):coords=np.column_stack(np.where(img>0))print(coords)print(coords.shape)angle =cv.minAreaRect(coords)[-1]    #最小外接矩形print(angle)if angle<-45:angle = -(90+angle)else:angle=-anglecenter = (w//2,h//2)M= cv.getRotationMatrix2D(center,angle,1.0) #传入中心和角度 得到旋转矩形rotated = cv.warpAffine(src,M,(w,h),flags=cv.INTER_CUBIC,borderMode=cv.BORDER_REPLICATE)cv.putText(rotated,'Angle:{:.2f} degrees'.format(angle),(10,30),cv.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)#绘制文字cv.imshow('Rotated',rotated)src= cv.imread('imageTextR.png')
(h,w)=src.shape[:2]
gray=cv.cvtColor(src,cv.COLOR_BGR2GRAY)
binary=binary(src)
Transformation(binary,src)
cv.imshow('src',src)
cv.imshow('binary',binary)
cv.waitKey(0)
4.1 灰度化以及预处理

不多赘述

4.2 二值化
ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV|cv.THRESH_OTSU)

在OpenCV中,cv2.threshold函数用于将图像转换为二值图像。您提供的代码片段ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)是使用cv2.threshold函数对灰度图像gray进行阈值处理,以创建一个二值图像binary

这里的参数解释如下:

  • gray:这是您要进行阈值处理的灰度图像。
  • 0:这是阈值处理的下限值。所有小于这个值的像素将被设置为0(通常是黑色)。
  • 255:这是阈值处理的上限值。所有大于这个值的像素将被设置为255(通常是白色)。
  • cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU:这是阈值处理的方法。cv2.THRESH_BINARY_INV表示使用二值反转阈值,即小于阈值的像素将被设置为255(白色),大于阈值的像素将被设置为0(黑色)。cv2.THRESH_OTSU表示使用Otsu’s方法来自动选择阈值。

Otsu’s方法是一种自动选择阈值的方法,它通过最大化类间方差来选择最佳阈值。这种方法通常用于图像分割,以区分前景和背景。

 

 

4.3 最小外接矩形 

首先获取所有非零坐标元素

coords=np.column_stack(np.where(binary>0))

在您提供的代码片段中,coords = np.column_stack(np.where(binary > 0)) 是一个用于获取二值图像中所有非零像素位置的坐标的方法。具体步骤如下:

  1. 创建二值图像:首先,您使用cv2.threshold函数创建了一个二值图像binary。在这个二值图像中,值为0的像素代表背景,而值为255的像素代表前景。

  2. 使用np.where获取非零像素位置np.where(binary > 0) 是一个NumPy函数,用于获取二值图像中所有非零像素的位置。这个函数返回一个包含所有非零像素坐标的元组,其中第一个元素是x坐标,第二个元素是y坐标。

  3. 将坐标堆叠为列向量:使用np.column_stack函数将坐标堆叠为列向量。这个操作将创建一个二维数组,其中每一行代表一个像素点的坐标。

然后寻找最小外接矩形 

 angle =cv.minAreaRect(coords)[-1]

在OpenCV中,cv2.minAreaRect函数用于找到图像中最小的外接矩形,并返回该矩形的旋转角度。这个函数通常用于对象检测和图像识别任务中。

cv2.minAreaRect函数的参数是一个包含像素点的坐标数组,这些点定义了一个多边形。函数返回的参数有三个:1.矩形的中心点 2.矩形的长和宽 3.矩形的旋转角度

在您提供的代码片段中,angle = cv2.minAreaRect(coords)[-1]的目的是获取最小外接矩形的旋转角度。coords是一个包含像素点的坐标数组,这些点定义了一个多边形,即您之前通过np.column_stack(np.where(binary > 0))获取的非零像素位置。

angle_p =cv.minAreaRect(coords)
box_points = cv.boxPoints(angle_p)
box_points = np.int0(box_points)
cv.circle(src, [146,284], 1, (0, 0, 255), 4)
srca = cv.drawContours(src, [box_points], -1, (0, 0, 255), 2)
》》》15.60267448425293

可以看到画出的外接矩形不能将文字全部包裹住,其角度为15.6,同样是以y轴正半轴为0°,顺时针为度数。

 

4.4 中心,角度,矩阵

cv.getRotationMatrix2D(center, angle, scale) → M

参数说明
center表示旋转中心坐标,二元元组 (x0, y0)。
angle表示旋转角度,单位为角度,逆时针为正数,顺时针为负数
scale表示缩放因子。

4.5 仿射变换

需要说明的是,不管是霍夫线变换还是最小外接矩形,都是为了获取图像的一个倾斜角度。按上面画出的外接矩形来进行仿射变换来本不能完成校正,但是因为文字与x轴正半轴夹角为15.5,然后最小外接矩形的角度刚好是15.6,经过angle=-angle变换后,输入到旋转矩阵的角度就为-15.5,然后仿射变换的旋转就是,正数就是逆时针旋转,负数就是顺时针旋转,所以将原图顺时针旋转后,就刚好校正了。

参考:

OpenCV实战之三 | 基于OpenCV实现图像校正 

 

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

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

相关文章

ue 材质贴图Tiling repeat

材质问题&#xff0c;如下 贴图显然不符合逻辑&#xff0c;太大&#xff0c;并且是一次性贴图 换一个红砖纹理&#xff0c;就看清了&#xff0c;砖太大了 修改&#xff1a; 拖出一个TexCoord&#xff0c;代表坐标&#xff0c;拖出一个参数&#xff0c;代表次数&#xff0c;如…

LDO芯片手册,实例应用分析

在进行电路设计时LDO是经常用到的&#xff0c;尤其在为芯片&#xff0c;晶振等敏感电路进行供电时应用更多&#xff0c;下面选取一款比较常用的LDO芯片&#xff0c;一起进行更深入的学习。 SGM2036特点简介 SGM2036&#xff0c;圣邦微一款比较常用的LDO芯片手册 可以先大致看…

用两个钟,我又在VMWARE上搞了一套内部网配置

最近要学es&#xff0c;所以打算自己用虚拟机搞个NAT&#xff0c;又搞了两个钟。为了不再费劲尝试&#xff0c;也为了造福大众&#xff0c;所以选择搞一份NAT笔记&#xff01;&#xff01;&#xff01;&#xff01; 1.初始化网关和DNS 我们给网关配置一个地址192.168.96.1&…

Vue41 ref属性

ref属性 ref是Vue提供的获取组件的属性 <template><div><h1 v-text"msg" ref"title"></h1><button ref"btn" click"showDOM">点我输出上方的DOM元素</button><MySchool ref"sch"…

浏览器扩展V3开发系列之 chrome.commands 快捷键的用法和案例

【作者主页】&#xff1a;小鱼神1024 【擅长领域】&#xff1a;JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 chrome.commands API 允许开发者使用快捷键来执行特定的命令。 在使用 chrome.commands API 之前必须…

【UE5.3】笔记3-静态网格体,BSP

静态网格体组件 主要有两个属性 一个是静态网格体&#xff1a;对应的也就是模型&#xff0c;比如fbx&#xff0c;maya&#xff0c;obj等格式 一个是材质&#xff1a;由各种贴图、渲染设置等&#xff0c;比如unity里的shader BSP画刷&#xff1a; 打开放置Actor选项卡&#…

【Linux详解】进程的状态 | 运行 阻塞 挂起 | 僵尸和孤儿状态

目录 操作系统中 运行状态 阻塞状态 进程状态转换 Linux系统中 查看进程状态 深度睡眠状态 T 暂停状态 Z 僵尸状态 孤儿状态 文章手稿 xmind: 引言 介绍系统中的进程状态及其管理方式。将通过结合操作系统原理和实际代码示例&#xff0c;详细说明进程的各种状态、转换…

【插件】IDEA这款插件Key Promoter X,爱到无法自拔

文章目录 为什么选择Key Promoter X&#xff1f;1. 提升开发效率2. 友好的学习曲线3. 可定制性强 安装和配置Key Promoter X1. 安装插件2. 配置插件 使用Key Promoter X个人使用体验1. 快捷键记忆2. 定制化功能3. 整体体验提升 总结 &#x1f389;欢迎来到Java学习路线专栏~探索…

flink输出中文乱码

flink输出中文乱码 &#xff08;1&#xff09;首先在/etc/profile.d/my_env.sh中加入下面这行数据 export LANGzh_CN.UTF-8&#xff08;2&#xff09;其次在flink配置文件中指定编码 [xxxhadoop102 flink-1.13.6]$ vim conf/flink-conf.yaml加入下面这行数据 env.java.opts:…

基于IM948(Low-cost IMU+蓝牙)模块的高精度PDR(Pedestrian Dead Reckoning)定位系统 — 可以提供模块和配套代码

一、背景与意义 行人PDR定位系统中的PDR&#xff08;Pedestrian Dead Reckoning&#xff0c;即行人航位推算&#xff09;背景意义在于其提供了一种在GPS信号不可用或不可靠的环境下&#xff0c;对行人进行精确定位和导航的解决方案。以下是关于PDR背景意义的详细描述&#xff1…

Linux服务升级:Almalinux 升级 WebCatlog桌面程序

目录 一、实验 1.环境 2.Almalinux 升级 WebCatlog桌面程序 二、问题 1.Ubuntu如何升级 WebCatlog桌面程序 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本软件IP备注Almalinux9.4 WebCatlog 192.168.204.150 &#xff08;2&#xff09;Termi…

【尚庭公寓SpringBoot + Vue 项目实战】移动端项目初始化(十九)

【尚庭公寓SpringBoot Vue 项目实战】移动端项目初始化&#xff08;十九&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】移动端项目初始化&#xff08;十九&#xff09;1、 SpringBoot配置2、Mybatis-Plus配置3、Knife4j配置4、导入基础代码5、导入接口定义代码6…

node 实现导出, 在导出excel中包含图片(附件)

如果想查看 node mySql 实现数据的导入导出&#xff0c;以及导入批量插入的sql语句&#xff0c;连接如下 node mySql 实现数据的导入导出&#xff0c;以及导入批量插入的sql语句-CSDN博客https://blog.csdn.net/snows_l/article/details/139998373 一、效果如图&#xff1a; 二…

文件管理—linux(基础IO)

目录 ​编辑 一、C语言文件接口&#xff08;库函数&#xff09; hello.c写文件 hello.c读文件 输出信息到显示器 stdin & stdout & stderr 二、系统文件I/O&#xff08;系统调用&#xff09; hello.c 写文件&#xff1a; hello.c读文件 接口介绍 open open…

电脑开机之后屏幕没有任何显示?怎么检查?

前言 最近有很多小伙伴来咨询&#xff0c;自己的电脑开机之后&#xff0c;屏幕真的是一点显示都没有&#xff0c;只有CPU风扇在转。 这个情况小白经常经常经常遇到&#xff0c;所以写一篇关于这个问题的排查教程。按照这个教程来排查&#xff0c;除非真的是硬件损坏&#xff…

AI音乐大模型:深度剖析创意与产业的双重变革

随着AI技术的飞速发展&#xff0c;音乐大模型在最近一个月内纷纷上线&#xff0c;这一变革性技术不仅颠覆了传统的音乐创作方式&#xff0c;更是对整个音乐产业及创意产业带来了深远的影响。本文将从多个维度出发&#xff0c;深度剖析AI音乐大模型对创意与产业的双重变革。 一、…

数据库 |试卷1试卷2

1.数据库语言四大语句 4.四大类&#xff08;DDL、DML、DQL、DCL&#xff09;_中度ddl-CSDN博客 数据定义&#xff08;data defination language&#xff09; 查询、创建、删除、使用 #查询所有数据库 show databases;#查询当前数据库 select database();#创建数据库 create …

关于导入springcloud项目一些jar加载不进去的问题处理

IntelliJ IDEA的Maven项目有时候通过右边Maven Projects面板的package或者install命令打包的时候&#xff0c;会报错导致打包失败&#xff0c;这是由于这两个命令打包前默认会运行tests测试&#xff0c;若测试失败则打包失败。但是有时候我们打包的时候一些项目配置是针对生产环…

办公软件汇总

1、OCR 1.1 pearOCR pearOCR 是一个免费的免费在线文字提取OCR工具网站。PearOCR界面简洁&#xff0c;所有过程均在网页端完成,无需下载任何软件&#xff0c;点开即用。官方地址&#xff1a;https://pearocr.com/ 参考&#xff1a;9款文字识别&#xff08;OCR&#xff09;工具…

【深度学习】GPT-3,Language Models are Few-Shot Learners(一)

论文&#xff1a; https://arxiv.org/abs/2005.14165 摘要 最近的研究表明&#xff0c;通过在大规模文本语料库上进行预训练&#xff0c;然后在特定任务上进行微调&#xff0c;可以在许多NLP任务和基准上取得显著的进展。虽然这种方法在结构上通常是任务无关的&#xff0c;但…