Opencv Python图像处理笔记一:图像、窗口基本操作

news2024/11/16 22:48:18

文章目录

  • 前言
  • 一、输入输出
    • 1.1 图片读取显示保存
    • 1.2 视频读取保存
    • 1.3 文件读取保存
  • 二、GUI
    • 2.1 窗口
    • 2.2 轨迹条
    • 2.3 画图
    • 2.4 鼠标回调
  • 三、图像入门操作
    • 3.1 颜色空间转化
    • 3.2 通道分离合并
    • 3.3 添加边框
    • 3.4 算数操作
  • 四、二值化
    • 4.1 普通
    • 4.2 自适应
    • 4.3 Otsu
  • 参考

前言

随着人工智能和计算机视觉技术的迅猛发展,OpenCV(Open source Computer Vision library)成为了广大开发者和研究者们不可或缺的利器之一。OpenCV 是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法,涵盖了从简单的图像处理操作到复杂的目标检测和跟踪等领域。

本文旨在帮助读者系统地学习 Opencv Python,从基础的图像输入输出开始,逐步深入到图像处理的各个领域,涵盖 GUI 编程、图像操作、二值化等多个重要主题。无论您是初学者还是有经验的开发者,本文都将提供清晰的指导和实用的示例,帮助您快速掌握 Opencv Python 的应用技巧。

  • github

    • https://github.com/opencv/opencv-python
    • https://github.com/opencv/opencv
  • 安装

    pip install opencv-python
    

一、输入输出

1.1 图片读取显示保存

import sys
import cv2 as cv

def main():   
    img = cv.imread("alice_color.png")
    if img is None:
        sys.exit("Could not read the image.")
    cv.imshow("Display window", img)
    k = cv.waitKey(0)
    if k == ord("q"):
        roi = img[100: 200, 100:200]
        roi[:] = 0
        cv.imwrite("alice_color_change.png", img)

if __name__ == '__main__':
    main()

demo01

1.2 视频读取保存

import cv2 as cv


def main():
    # 定义解码器 MJPG (.mp4), DIVX (.avi), X264 (.mkv)
    fourcc = cv.VideoWriter_fourcc(*'MJPG')
    # 设置 帧率 分辨率
    # 注意, 这里设置分辨率需要与你摄像头或者读取的文件的分辨率保持一致, 否则不会写入数据
    out = cv.VideoWriter('output.avi', fourcc, 20.0, (960, 506))

    # cap = cv.VideoCapture(0)
    cap = cv.VideoCapture('test.mp4')
    if not cap.isOpened():
        print("Cannot open camera")
        exit()
    while True:
        # Capture frame-by-frame
        ret, frame = cap.read()
        # if frame is read correctly ret is True
        if not ret:
            print("Can't receive frame (stream end?). Exiting ...")
            break
        # Our operations on the frame come here
        cv.waitKey(1)
        cv.imshow('frame', frame)
        # 翻转图像
        frame = cv.flip(frame, 0)

        out.write(frame)

    # When everything done, release the capture
    cap.release()
    out.release()
    cv.destroyAllWindows()


if __name__ == '__main__':
    main()

demo_02_video_read_write

1.3 文件读取保存

opencv 还支持持久化,将数据以xml,yml,json文件保存,并读取

import cv2 as cv
import numpy as np

def main():
    write()
    read()

def write():  

    # 创建FileStorage对象并打开一个文件用于写入
    fs = cv.FileStorage('test.xml', cv.FILE_STORAGE_WRITE)
    
    # 写入一些数据
    fs.write('First_Integer', 123)
    fs.write('First_String', 'Hello')
    
    # 写入一个矩阵
    mat = np.eye(2, 3, dtype=np.uint8)
    fs.write('Matrix', mat)
    
    # 写入一个复杂的数据结构
    fs.write('List', (1, 2, 3))
    
    # 关闭FileStorage对象
    fs.release()

def read():
    fs = cv.FileStorage('test.xml', cv.FILE_STORAGE_READ)
 
    # 读取数据
    if not fs.isOpened():
        print("Error: Unable to open file.")
        exit()

    First_Integer = fs.getNode('First_Integer').real()
    First_String = fs.getNode('First_String').string()
    Matrix = fs.getNode('Matrix').mat()
    List = fs.getNode('List').mat()

    print(First_Integer)
    print(First_String)
    print(Matrix)
    print(List)

    fs.release()
    
if __name__ == '__main__':
    main()

demo_03_xml_file.png

二、GUI

2.1 窗口

import cv2 as cv
import numpy as np

def main():
    # 名字为first 和second 两个窗口
    # cv.namedWindow(窗口名称, 窗口属性)
    """
    WindowFlags:
        WINDOW_NORMAL : user can resize the window
        WINDOW_AUTOSIZE : user cannot resize the window, the size is constrainted by the image displayed 
        WINDOW_OPENGL : window with opengl support
        WINDOW_FULLSCREEN : change the window to fullscreen
        WINDOW_FREERATIO : the image expends as much as it can 自由比例 
        WINDOW_KEEPRATIO : 保持比例
        WINDOW_GUI_EXPANDED : status bar and tool bar
        WINDOW_GUI_NORMAL  : old fashious way
    """
    cv.namedWindow('first', cv.WINDOW_AUTOSIZE)
    cv.namedWindow('second', cv.WINDOW_NORMAL)

    img = cv.imread('alice_color.png')
    img_changed = cv.imread('alice_color_change.png')

    cv.imshow('first', img)

    # 更改窗口尺寸
    cv.resizeWindow('second', 640, 640)
    cv.imshow('second', img_changed)
    
    # 等待键盘输入,参数为等待时长,单位: ms。0为无限等待
    k = cv.waitKey(0)
    if k == ord("q"):
        cv.destroyAllWindows()
        

if __name__ == '__main__':
    main()

demo_04_windows

2.2 轨迹条

import cv2 as cv
import numpy as np

def callback(index):
    pass

def main():
    winname = "trackbar"
    cv.namedWindow(winname, cv.WINDOW_NORMAL)
    cv.resizeWindow(winname, 640, 480)

    # 创建trackbar控件
    # argument:
    # trackbarname, winname, value, count, callback, userdata
    cv.createTrackbar('R', winname, 0, 255, callback)
    cv.createTrackbar('G', winname, 0, 255, callback)
    cv.createTrackbar('B', winname, 0, 255, callback)

    # 创建初始图像
    img = np.zeros(shape=(640, 480, 3), dtype=np.uint8)

    # 显示图像:
    while True:
        # 读取控件值:
        r = cv.getTrackbarPos('R', winname)
        g = cv.getTrackbarPos('G', winname)
        b = cv.getTrackbarPos('B', winname)

        # b,g,r这个通道数, 在opencv中, rgb通道数是反过来的
        img[:] = [b, g, r]

        # 显示图像
        cv.imshow(winname, img)

        # 等待键盘
        if cv.waitKey(1) & 0xFF == ord('q'):
            break

    cv.destroyAllWindows()
        

if __name__ == '__main__':
    main()

demo_05_trackbar

2.3 画图

import cv2 as cv
import numpy as np
from PIL import Image, ImageDraw, ImageFont


def paint_chinese_opencv(im, textstr, position, fontsize, color):
    # opencv输出中文
    img_PIL = Image.fromarray(cv.cvtColor(
        im, cv.COLOR_BGR2RGB))  # 图像从OpenCV格式转换成PIL格式
    font = ImageFont.truetype(
        r'C:\Windows\Fonts\simfang.ttf', fontsize, encoding="utf-8")
    # color = (255,0,0) # 字体颜色
    # position = (100,100)# 文字输出位置
    draw = ImageDraw.Draw(img_PIL)
    draw.text(
        position, textstr, font=font,
        fill=color)
    img = cv.cvtColor(np.asarray(img_PIL), cv.COLOR_RGB2BGR)  # PIL图片转OpenCV 图片
    return img


def main():
    img = np.zeros((512, 512, 3), np.uint8)

    # 划线
    cv.line(img,
            (0, 0), (511, 511),  # 两点
            color=(255, 0, 0),  # 颜色
            thickness=5,  # 线宽,默认为1
            lineType=4)  # 线类型 有 cv.FILLED, cv.LINE_4, cv.LINE_8, cv.LINE_AA 这4种, 默认为LINE_8,

    # 画矩形,左上角和右下角,其余同上
    cv.rectangle(img, pt1=(384, 0), pt2=(510, 128), color=(0, 255, 0))

    # 画圆,圆心,半径
    cv.circle(img, center=(447, 63), radius=63,
              color=(0, 0, 255), thickness=cv.FILLED)

    # 画椭圆
    cv.ellipse(img,
               center=(256, 256),  # 中心坐标
               axes=(100, 50),  # 长轴,短轴 一半
               angle=0,  # 椭圆沿逆时针方向的旋转角度
               startAngle=0,
               endAngle=180,  # 开始角和结束角表示从主轴向顺时针方向测量的椭圆弧的开始和结束
               color=255,  # 颜色
               thickness=2,
               lineType=cv.FILLED)

    pts = np.array([[10, 5], [20, 30], [70, 20], [50, 10]], np.int32)
    pts = pts.reshape((-1, 1, 2))

    cv.polylines(img, [pts],
                 isClosed=True,  # 是否闭合
                 color=(0, 255, 255))

    cv.putText(img, text='OpenCV',
               org=(10, 500),  # 左下角
               fontFace=cv.FONT_HERSHEY_SIMPLEX,  # 字体
               fontScale=4, # 字体缩放
               color=(255, 255, 255),
               thickness=2,
               lineType=cv.LINE_AA)

    img = paint_chinese_opencv(img, '中文', (255, 255), 40, (255, 255, 255))

    cv.imshow('draw', img)
    k = cv.waitKey(0)
    if k == ord("q"):
        cv.destroyAllWindows()


if __name__ == '__main__':
    main()

demo_06_draw

2.4 鼠标回调

import cv2 as cv
import numpy as np


# 生成全黑图像
img = np.zeros((480, 640, 3), np.uint8)  

# 定义鼠标回调函数画圆
def draw_circle(event,x,y,flags,param):
    # 左键双击
    if event == cv.EVENT_LBUTTONDBLCLK:
        cv.circle(img,(x,y),50,(255,255,0),-1)



def main():
    WINDOW_NAME = "mouse"
    # 创建桌面
    cv.namedWindow(WINDOW_NAME, cv.WINDOW_NORMAL)
    cv.resizeWindow(WINDOW_NAME, 640, 480)

    # 设置鼠标回调, 绑定窗口
    cv.setMouseCallback(WINDOW_NAME, draw_circle, "123")

    # 显示图像
    while True:
        cv.imshow(WINDOW_NAME, img)
        if cv.waitKey(20) & 0xFF == ord('q'):
            break

    cv.destroyAllWindows()
        

if __name__ == '__main__':
    main()

demo_07_mouse

三、图像入门操作

3.1 颜色空间转化

import cv2 as cv
import numpy as np


def callback(index):
    pass


def main():
    winname = "color"
    trackbarname = "colorspace"
    cv.namedWindow(winname, flags=cv.WINDOW_NORMAL)
    cv.resizeWindow(winname, 600, 800)

    color_space_list = [cv.COLOR_BGR2RGB, cv.COLOR_BGR2BGRA,
                        cv.COLOR_BGR2GRAY, cv.COLOR_BGR2HSV, cv.COLOR_BGR2YUV]  # 格式转换队列

    # 创建Trackbar
    cv.createTrackbar(trackbarname, winname, 0, len(
        color_space_list)-1, callback)

    # 读取图片
    img = cv.imread("alice_color.png")

    # 显示图像
    while True:
        color_space_index = cv.getTrackbarPos(trackbarname, winname)

        # 颜色空间转换 -> cvtColor(src, colorSpace)颜色转换
        cvt_img = cv.cvtColor(img, color_space_list[color_space_index])

        cv.imshow(winname, cvt_img)

        if cv.waitKey(1) & 0xFF == ord('q'):
            break
    cv.destroyAllWindows()


if __name__ == '__main__':
    main()

color

3.2 通道分离合并

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def main():
    img = cv.imread("lena.png")

    # 分割出来的b,g,r每一个都是一个单个矩阵.
    # b, g, r = cv.split(img)
    # 直接操作可以用索引
    b, g, r = img[:, :, 0], img[:, :, 1], img[:, :, 2]

    zeros = np.zeros(img.shape[:2], dtype='uint8')

    title = ['ORIGINAL', 'B', 'G', 'R']
    # 对应的图像
    imgs = [img, cv.merge([b, zeros, zeros]), cv.merge(
        [zeros, g, zeros]), cv.merge([zeros, zeros, r])]

    for i in range(len(imgs)):
        plt.subplot(2, 2, i + 1)
        plt.imshow(cv.cvtColor(imgs[i], cv.COLOR_BGR2RGB))
        plt.title(title[i])
        plt.axis('off')

    plt.show()

    cv.waitKey(0)

    cv.destroyAllWindows()


if __name__ == '__main__':
    main()

demo_09_color_channel

3.3 添加边框

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def main():
    BLUE = [255, 0, 0]

    img1 = cv.imread('lena.png')
    assert img1 is not None, "file could not be read, check with os.path.exists()"

    width = 20
    # cv.BORDER_REPLICATE 边界颜色被复制                    eg: aaaaaa|abcdefgh|hhhhhhh
    # cv.BORDER_REFLECT  边界颜色被镜像                     eg: fedcba|abcdefgh|hgfedcb
    # cv.BORDER_REFLECT_101  和上面类似,有点不同,这是默认值 eg: gfedcb|abcdefgh|gfedcba
    # cv.BORDER_WRAP                                       eg: cdefgh|abcdefgh|abcdefg
    # cv.BORDER_CONSTANT  给定边界颜色
    replicate = cv.copyMakeBorder(
        img1, width, width, width, width, cv.BORDER_REPLICATE)
    reflect = cv.copyMakeBorder(
        img1, width, width, width, width, cv.BORDER_REFLECT)
    reflect101 = cv.copyMakeBorder(
        img1, width, width, width, width, cv.BORDER_REFLECT_101)
    wrap = cv.copyMakeBorder(img1, width, width, width, width, cv.BORDER_WRAP)
    constant = cv.copyMakeBorder(
        img1, width, width, width, width, cv.BORDER_CONSTANT, value=BLUE)

    title = ['ORIGINAL', 'REPLICATE', 'REFLECT',
             'REFLECT_101', 'WAP', 'CONSTANT']
    # 对应的图像
    imgs = [img1, replicate, reflect, reflect101,
            wrap, constant]

    for i in range(len(imgs)):
        plt.subplot(2, 3, i + 1)
        plt.imshow(cv.cvtColor(imgs[i], cv.COLOR_BGR2RGB))
        plt.title(title[i])
        plt.axis('off')

    plt.show()


if __name__ == '__main__':
    main()

border

3.4 算数操作

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def main():

    img = cv.imread('lena.png')
    img_girl = cv.imread('girl.png')
    assert img & img_girl is not None, "file could not be read, check with os.path.exists()"

    pixel = img[255, 255]
    print(pixel)                    # [ 78  70 181]
    print(pixel.dtype)              # uint8
    print(img.item(255, 255, 2))    # 181

    x = np.uint8([250])
    y = np.uint8([10])

    print(cv.add(x, y, dtype=cv.CV_8UC3))  # [[255],[0],[0],[0]]
    print(x + y)  # [6]

    # 两张图片按照权重叠加,需要宽高一样大
    img_new = cv.addWeighted(img_girl, 0.7, img, 0.3, 0)

    # 对图片进行位运算 取反、与、或、异或
    img_bit_not = cv.bitwise_not(img)
    img_bit_and = cv.bitwise_and(img, img_girl)
    img_bit_or = cv.bitwise_or(img, img_girl)
    img_bit_xor = cv.bitwise_xor(img, img_girl)

    title = ['Lena', 'Girl', 'addWeight', 'Not', 'And', 'Or', 'Xor']
    # 对应的图像
    imgs = [img, img_girl, img_new, img_bit_not,
            img_bit_and, img_bit_or, img_bit_xor]

    for i in range(len(imgs)):
        plt.subplot(3, 3, i + 1)
        plt.imshow(cv.cvtColor(imgs[i], cv.COLOR_BGR2RGB))
        plt.title(title[i])
        plt.axis('off')

    roi = img_girl[280:340, 330:390]
    roi[:] = 255
    plt.subplot(338), plt.imshow(cv.cvtColor(img_girl, cv.COLOR_BGR2RGB)), plt.title(
        'Roi'), plt.axis('off')

    plt.show()

    cv.waitKey(0)

    cv.destroyAllWindows()


if __name__ == '__main__':
    main()

demo_11_arithmetic_op

四、二值化

4.1 普通

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


max_value = 255
max_type = 4
max_binary_value = 255
trackbar_type = 'Type'
trackbar_value = 'Value'
window_name = 'Threshold Demo'


def callback(val):
    # 0: Binary                         给定threshold_value,大于它为255,小于为0
    # 1: Binary Inverted                给定threshold_value,大于它为0,小于为255
    # 2: Threshold Truncated            给定threshold_value,大于它为threshold_value,小于则不变
    # 3: Threshold to Zero              给定threshold_value,大于它不变,小于则为0
    # 4: Threshold to Zero Inverted     给定threshold_value,大于它为0,小于则不变
    threshold_type = cv.getTrackbarPos(trackbar_type, window_name)
    threshold_value = cv.getTrackbarPos(trackbar_value, window_name)
    _, dst = cv.threshold(img_gray, threshold_value,
                          max_binary_value, threshold_type)
    cv.imshow(window_name, dst)


def main():

    global img_gray
    img_gray = cv.imread('lena.png', cv.IMREAD_GRAYSCALE)

    cv.namedWindow(window_name)
    cv.resizeWindow(window_name, 512, 512)

    cv.createTrackbar(trackbar_type, window_name, 0, max_type, callback)
    cv.createTrackbar(trackbar_value, window_name, 0, max_value, callback)

    cv.waitKey(0)

    cv.destroyAllWindows()


if __name__ == '__main__':
    main()

demo_12_threshold

4.2 自适应

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def main():

    img = cv.imread('sudoku.png', cv.IMREAD_GRAYSCALE)
    assert img is not None, "file could not be read, check with os.path.exists()"
    img = cv.medianBlur(img, 5)

    ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)

    #  每个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的
    #  THRESH_BINARY      ===>    dst(x, y) = maxValue if src(x, y) > T(x, y) else 0
    #  THRESH_BINARY_INV  ===>    dst(x, y) = 0 if src(x, y) > T(x, y) else maxValue
    #  maxValue 非零值
    #  adaptiveMethod 自适应算法T
    #        1. cv.ADAPTIVE_THRESH_MEAN_C       计算邻域的均值 再减C
    #        2. cv.ADAPTIVE_THRESH_GAUSSIAN_C   计算邻域的高斯加权和,再减C
    #  thresholdType 必须是 cv.THRESH_BINARY 或 cv.THRESH_BINARY_INV
    #  blockSize   邻域大小 blockSize * blockSize, 一般用3,5,7等等
    #  C  要减去的值
    th2 = cv.adaptiveThreshold(img, maxValue=255, adaptiveMethod=cv.ADAPTIVE_THRESH_MEAN_C,
                               thresholdType=cv.THRESH_BINARY, blockSize=11, C=2)
    th3 = cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                               cv.THRESH_BINARY, 11, 2)

    titles = ['Original Image', 'Global Thresholding (v = 127)',
              'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
    images = [img, th1, th2, th3]

    for i in range(4):
        plt.subplot(2, 2, i+1), plt.imshow(images[i], 'gray')
        plt.title(titles[i])
        plt.xticks([]), plt.yticks([])
    plt.show()


if __name__ == '__main__':
    main()

demo_13_adaptive_threshold

4.3 Otsu

在使用 threshold 方法阈值设置中,我们可以使用任意选择的值作为阈值。相比之下,Otsu 二值化不需要手动选择一个值,可以直接设为0

考虑一个只有两个不同图像值的图像(双峰图像),其中直方图将只由两个峰组成。一个很好的阈值应该是在这两个值的中间值。

Otsu 从图像直方图中确定一个最优的全局阈值。该算法找到最优阈值,并作为第一个输出返回。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


def main():

    img = cv.imread('southeast.jpg', cv.IMREAD_GRAYSCALE)
    assert img is not None, "file could not be read, check with os.path.exists()"

    # global thresholding
    ret1, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)

    # Otsu's thresholding
    ret2, th2 = cv.threshold(img, 0, 255, cv.THRESH_BINARY+cv.THRESH_OTSU)

    # Otsu's thresholding after Gaussian filtering
    blur = cv.GaussianBlur(img, (7, 7), 0)
    ret3, th3 = cv.threshold(blur, 0, 255, cv.THRESH_BINARY+cv.THRESH_OTSU)

    # plot all the images and their histograms
    images = [img, 0, th1,
              img, 0, th2,
              blur, 0, th3]
    titles = ['Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)',
              'Original Noisy Image', 'Histogram', "Otsu's Thresholding",
              'Gaussian filtered Image', 'Histogram', "Otsu's Thresholding"]

    for i in range(3):
        plt.subplot(3, 3, i*3+1), plt.imshow(images[i*3], 'gray')
        plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
        plt.subplot(3, 3, i*3+2), plt.hist(images[i*3].ravel(), 256)
        plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
        plt.subplot(3, 3, i*3+3), plt.imshow(images[i*3+2], 'gray')
        plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
    plt.show()


if __name__ == '__main__':
    main()

demo_14_otsu_threshold

参考

  1. https://docs.opencv.org/4.x/d6/d00/tutorial_py_root.html

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

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

相关文章

227基于matlab的作业调度问题

基于matlab的作业调度问题。采用遗传算法,解决作业调度问题。一共三个作业,每个作业有不同的时间长度和紧急程度,超过时间会有惩罚措施。通过遗传算法计算出最好的作业安排,使得惩罚最小,获益最大。最终结果通过GUI用甘…

了解IPS和IDS:这5个差异将改变你的安全观念!

IPS 代表 入侵防御系统(Intrusion Prevention System),它是 IDS 的进一步发展,不仅具备检测攻击的能力,还能在检测到攻击后主动采取措施阻止攻击。IPS 通常部署在防火墙和网络设备之间,能够深度感知并检测流…

第八周学习笔记DAY.1-异常

本课目标 了解异常概念 理解Java异常处理机制 会捕捉异常 会抛出异常 了解Java异常体系结构 什么是异常 异常是指在程序的运行过程中所发生的不正常的事件,它会中断正在运行的程序 生活中,根据不同的异常进行相应的处理,而不会就此中断…

支持中文繁体,支持同时配置并启用飞书和Lark认证,JumpServer堡垒机v3.10.8 LTS版本发布

2024年4月22日,JumpServer开源堡垒机正式发布v3.10.8 LTS版本。JumpServer开源项目组将对v3.10 LTS版本提供长期的支持和优化,并定期迭代发布小版本。欢迎广大社区用户升级至v3.10 LTS最新版本,以获得更佳的使用体验。 在v3.10.8 LTS版本中&…

【js】解决读取文件源内容总是得到默认index.html

在项目开发中,资源的获取都可以通过网络,所以获取文件内容,只需要将文件地址作为请求发送即可 读取文件源内容 const path 资源地址(必须是绝对路径)fetch(path).then((response) > {if (!response.ok) {throw ne…

我与C++的爱恋:日期计算器

​ ​ 🔥个人主页:guoguoqiang. 🔥专栏:我与C的爱恋 朋友们大家好啊,在我们学习了默认成员函数后,我们通过上述内容,来实现一个简易的日期计算器。 ​ ​ 头文件的声明 #pragma once #incl…

计算机服务器中了locked勒索病毒怎么办,locked勒索病毒解密工具流程步骤

随着网络技术的不断应用与发展,越来越多的企业离不开网络,网络大大提升了企业的办公效率水平,也为企业的带来快速发展,对于企业来说,网络数据安全成为了大家关心的主要话题。近日,云天数据恢复中心接到多家…

Spring - 2 ( 14000 字 Spring 入门级教程 )

一:Spring Web MVC⼊⻔ Spring Web MVC 是⼀个 Web 框架,简称之为: Spring MVC 要真正的理解什么是 Spring MVC?我们⾸先要搞清楚什么是 MVC? 1.1 MVC 定义 MVC 是 Model View Controller 的缩写,它是软件⼯程中的…

丰田是如何用精益理念改变制造业的?

丰田,这个全球知名的汽车制造商,不仅以其高质量的产品赢得了消费者的信赖,更以其独特的精益理念深刻改变了整个制造业的面貌。那么,丰田究竟是如何用精益理念引领制造业变革的呢?天行健精益管理培训公司解析如下&#…

了解BACnet的对象模型 (三)

文章目录 前言18个对象BACnet 对象的属性设备对象(Device)的属性输入输出值对象类型及其属性 在代码中的表达Device对象的属性模拟输入对象的属性 小结 前言 在楼宇自控网络中,各种设备之间要进行数据交换,为了能够实现设备的互操…

[C++][算法基础]求组合数(II)

给定 𝑛 组询问,每组询问给定两个整数 𝑎,𝑏,请你输出 的值。 输入格式 第一行包含整数 𝑛。 接下来 𝑛 行,每行包含一组 𝑎 和 𝑏。 输出格…

【Java框架】SpringMVC(二)——SpringMVC数据交互

目录 前后端数据交互RequestMapping注解基于RequestMapping注解设置接口的请求方式RequestMapping注解的常用属性一个方法配置多个接口method属性params属性headers属性consumes属性produces属性 SpringMVC中的参数传递默认单个简单参数默认多个简单参数默认参数中有基本数据类…

机器学习-11-基于多模态特征融合的图像文本检索

总结 本系列是机器学习课程的系列课程,主要介绍机器学习中图像文本检索技术。此技术把自然语言处理和图像处理进行了融合。 参考 2024年(第12届)“泰迪杯”数据挖掘挑战赛 图像特征提取(VGG和Resnet特征提取卷积过程详解&…

Python 比较文本文件

1、问题背景 我们需要比较一个文本文件 F 与路径下多个其他文本文件之间的差异。我们已经编写了以下代码,但只能输出一个文件的比较结果。我们需要修改代码,以便比较所有文件并打印所有结果。 import difflib import fnmatch import osfilelist[] f op…

Linux 网络操作命令Telnet

Telnet 尽管 Telnet 已经逐渐被更安全的 SSH 协议所取代,但在某些特定场景下,如对旧系统的维护或教育目的,Telnet 仍然有其使用价值。本文将介绍如何在 Linux 系统中安装 Telnet 客户端,以及如何使用它进行远程登录。 用户使用 t…

基于SpringBoot+Vue的网上摄影工作室(含源码数据库+文档免费送)

项目演示视频: 基于SpringBootVue的网上摄影工作室(含源码数据库文档免费送) 基于SpringBootVue的网上摄影工作室(含源码数据库文档免费送) 开发系统:Windows10 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工…

JEECG表格选中状态怎么去掉

官网代码(在取消选中状态的时候不生效) rowSelection() {return {onChange: (selectedRowKeys, selectedRows) > {console.log(selectedRowKeys: ${selectedRowKeys}, selectedRows: , selectedRows);},getCheckboxProps: record > ({props: {disa…

亚马逊、Lazada、速卖通怎么提高复购率?如何利用自养号测评实现销量飙升

对于跨境卖家来说,抓住客户是最重要的,很多卖家都把大部分心思放在如何吸引新客户上,忽视了已有客户的维护。其实相较于投广告、报秒杀活动吸引新客户,维护好已有客户,提升复购率的成本更低。当然,维护好客…

微软如何打造数字零售力航母系列科普02 --- 微软低代码应用平台加速企业创新 - 解放企业数字零售力

微软低代码应用平台推动企业创新- 解放企业数字零售力 微软在2023年GARTNER发布的魔力象限图中处于头部领先(leader)地位。 其LCAP产品是Microsoft Power Apps,扩展了AI Builder、Dataverse、Power Automate和Power Pages,这些都包…

Java 基础知识易错记录

Java 基础知识易错记录 ①运算符 ②continue和break ③成员变量 局部变量 ④switch case ⑤StringBuffer StringBuilder ⑥重载 重写 ⑦throw throws 运算符 public static void main(String[] args) {int a 1;System.out.println(a);System.out.println(a);}在后&#xff…