OpenCV快速入门:窗口交互

news2024/9/25 11:19:30

文章目录

  • 前言
  • 一、鼠标操作
    • 1.1 鼠标操作简介
    • 1.2 鼠标事件类型(event类型)
    • 1.3 鼠标事件标志(flags)
    • 1.4 代码示例
      • 1.4.1 获取鼠标坐标位置
      • 1.4.2 监听鼠标滚轮事件
      • 1.4.3 在图像中显示鼠标坐标
  • 二、键盘操作
    • 2.1 代码示例
    • 2.2 waitKey的等待方法
  • 三、添加窗口控件
    • 3.1 滑动条(Trackbar)的基本使用
    • 3.2 自定义滑动条回调函数
  • 四、实现鼠标跟随绘制方框的交互效果
    • 4.1 代码实现
    • 4.2 代码解析
    • 4.3 运行代码
  • 五、自由调节窗口图像的尺寸
    • 5.1 代码实现
    • 5.2 代码解释
    • 5.3 运行代码
  • 六、中文显示乱码问题
    • 6.1 实现步骤
    • 6.2 代码实现
  • 总结


前言

OpenCV是一种强大的计算机视觉库,广泛用于图像处理和计算机视觉应用。本文将介绍OpenCV中的窗口交互功能,重点关注鼠标和键盘的操作,以及如何添加窗口控件来实现更丰富的用户体验。
OpenCV Logo

一、鼠标操作

1.1 鼠标操作简介

OpenCV提供了丰富的鼠标交互功能,包括但不限于:

  • 获取鼠标的坐标位置
  • 监听鼠标点击事件
  • 监听鼠标滚轮事件

1.2 鼠标事件类型(event类型)

在OpenCV中,通过设置鼠标回调函数,我们可以处理各种鼠标事件。
以下是一些常见的鼠标事件类型:

  1. EVENT_LBUTTONDBLCLK(左键双击) = 7
  2. EVENT_LBUTTONDOWN(左键按下) = 1
  3. EVENT_LBUTTONUP(左键释放) = 4
  4. EVENT_MBUTTONDBLCLK(中键双击) = 9
  5. EVENT_MBUTTONDOWN(中键按下) = 3
  6. EVENT_MBUTTONUP(中键释放) = 6
  7. EVENT_MOUSEHWHEEL(鼠标横向滚轮滚动) = 11
  8. EVENT_MOUSEMOVE(鼠标移动) = 0
  9. EVENT_MOUSEWHEEL(鼠标滚轮滚动) = 10
  10. EVENT_RBUTTONDBLCLK(右键双击) = 8
  11. EVENT_RBUTTONDOWN(右键按下) = 2
  12. EVENT_RBUTTONUP(右键释放) = 5

1.3 鼠标事件标志(flags)

以下是一些常见的鼠标事件标志:

  1. EVENT_FLAG_ALTKEY(Alt键按下) = 32
  2. EVENT_FLAG_CTRLKEY(Ctrl键按下) = 8
  3. EVENT_FLAG_LBUTTON(左键按下) = 1
  4. EVENT_FLAG_MBUTTON(中键按下) = 4
  5. EVENT_FLAG_RBUTTON(右键按下) = 2
  6. EVENT_FLAG_SHIFTKEY(Shift键按下) = 16

通过设置鼠标回调函数,我们可以根据这些事件类型和标志来执行相应的操作。例如,在左键点击时执行某些操作,在鼠标移动时显示坐标信息,或者通过滚轮事件来放大或缩小图像。这为图像处理和计算机视觉应用提供了灵活的交互性。

1.4 代码示例

让我们看一个简单的例子,如何通过OpenCV获取鼠标的坐标位置:

import cv2

def resize_image(factor):
    global image
    height, width = image.shape[:2]
    new_height = int(height * factor)
    new_width = int(width * factor)
    image = cv2.resize(image, (new_width, new_height))
    cv2.imshow("Image", image)


def mouse_callback(event, x, y, flags, param):
    global image
    if event == cv2.EVENT_LBUTTONDOWN:
        print(f"左键点击坐标:({x}, {y})")
    elif event == cv2.EVENT_RBUTTONDOWN:
        print(f"右键点击坐标:({x}, {y})")
    elif event == cv2.EVENT_MBUTTONDOWN:
        print(f"中键点击坐标:({x}, {y})")
    elif event == cv2.EVENT_MOUSEWHEEL:
        delta = flags
        if delta > 0:  # 滚轮向上滚动,放大图像
            resize_image(1.1)
        elif delta < 0:  # 滚轮向下滚动,缩小图像
            resize_image(0.9)
    elif event == cv2.EVENT_MOUSEMOVE:
        # 在图像左上角显示坐标
        coord_text = f"({x}, {y})"
        image_copy = cv2.putText(image.copy(), coord_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
        cv2.imshow("Image", image_copy)


# 创建图像窗口
cv2.namedWindow("Image")
# 设置鼠标回调函数
cv2.setMouseCallback("Image", mouse_callback)
# 读取图像
image = cv2.imread("tulips.jpg")
# 在窗口中显示图像
cv2.imshow("Image", image.copy())
# 等待用户按下任意键退出
cv2.waitKey(0)
# 关闭窗口
cv2.destroyAllWindows()

tulips

在上述代码中,我们通过OpenCV实现了鼠标的各种操作,并结合了图像处理和显示的功能,让用户能够更直观地感受到鼠标事件的影响。

1.4.1 获取鼠标坐标位置

通过设置鼠标回调函数 cv2.setMouseCallback,我们可以监听鼠标的各种事件。在这个例子中,我们主要关注了鼠标左键、右键、中键的点击事件,以及鼠标的滚轮事件。当鼠标左键、右键、中键被点击时,我们在控制台输出了相应的坐标信息。

if event == cv2.EVENT_LBUTTONDOWN:
    print(f"左键点击坐标:({x}, {y})")
elif event == cv2.EVENT_RBUTTONDOWN:
    print(f"右键点击坐标:({x}, {y})")
elif event == cv2.EVENT_MBUTTONDOWN:
    print(f"中键点击坐标:({x}, {y})")

1.4.2 监听鼠标滚轮事件

通过监听鼠标滚轮事件,我们可以实现图像的放大和缩小。在这个例子中,当鼠标滚轮向上滚动时,图像放大1.1倍;当鼠标滚轮向下滚动时,图像缩小0.9倍。

elif event == cv2.EVENT_MOUSEWHEEL:
    delta = flags
    if delta > 0:  # 滚轮向上滚动,放大图像
        resize_image(1.1)
    elif delta < 0:  # 滚轮向下滚动,缩小图像
        resize_image(0.9)

1.4.3 在图像中显示鼠标坐标

通过在图像上绘制文本,我们在图像左上角显示了当前鼠标的坐标位置。这使得用户可以实时了解鼠标相对于图像的位置。

elif event == cv2.EVENT_MOUSEMOVE:
    # 在图像左上角显示坐标
    coord_text = f"({x}, {y})"
    image_copy = cv2.putText(image.copy(), coord_text, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    cv2.imshow("Image", image_copy)

通过这些功能的组合,我们实现了一个简单而有趣的OpenCV窗口交互示例,展示了鼠标事件如何影响图像的显示和处理。这对于图像处理和计算机视觉应用中的交互性操作具有很大的实用性。

二、键盘操作

OpenCV不仅支持强大的图像处理功能,还提供了灵活的键盘交互功能,使得用户能够通过键盘来控制图像的显示和处理。我们将简要探讨waitKey的操作以及等待方法的使用。

2.1 代码示例

在OpenCV中,我们可以通过监听键盘按键事件来执行相应的操作。以下是一个简单的示例,演示了如何通过键盘按下事件来实现图像的放大和缩小:

import cv2


def resize_image(factor):
    global image
    height, width = image.shape[:2]
    new_height = int(height * factor)
    new_width = int(width * factor)
    image = cv2.resize(image, (new_width, new_height))
    cv2.imshow("Image", image)


# 读取图像
image = cv2.imread("tulips.jpg")

# 创建图像窗口
cv2.namedWindow("Image")
cv2.imshow("Image", image)

while True:
    key = cv2.waitKey(0)

    if key == ord('q'):  # 按下 'q' 键退出循环
        break
    elif key == ord('+'):  # 按下 '+' 键放大图像
        resize_image(1.1)
    elif key == ord('-'):  # 按下 '-' 键缩小图像
        resize_image(0.9)
# 关闭窗口
cv2.destroyAllWindows()

在这个例子中,我们通过cv2.waitKey(0)监听键盘按键事件,ord函数将字符转换为对应的ASCII码。按下 ‘q’ 键退出循环,按下 ‘+’ 键放大图像,按下 ‘-’ 键缩小图像。这样,用户可以通过简单的键盘操作来改变图像的大小。
注:输入 'q' 时,需要在英文输入法的情况下按下。

2.2 waitKey的等待方法

cv2.waitKey方法不仅用于检测按键事件,还可以设置一个参数,表示等待时间(毫秒)。

# 等待1秒
cv2.waitKey(1000)
# 关闭窗口
cv2.destroyAllWindows()

通过这些简单而实用的键盘交互技巧,我们可以更灵活地控制OpenCV中图像的显示和处理,使得图像处理过程更加交互化。

三、添加窗口控件

在OpenCV中,通过添加窗口控件,我们可以实现更丰富的图形用户界面(GUI),使用户能够通过滑动条、按钮等控件与图像进行交互。这里将以滑动条为例,详细描述如何在OpenCV窗口中添加控件。

3.1 滑动条(Trackbar)的基本使用

滑动条是OpenCV中最常用的窗口控件之一,可以用于调整参数,比如图像的亮度、对比度等。以下是一个简单的例子,演示如何在OpenCV窗口中添加滑动条:

import cv2

def on_trackbar_change(value):
    # 当滑动条数值改变时调用的回调函数
    print(f"滑动条数值:{value}")

# 创建一个图像窗口
cv2.namedWindow("Image")

# 创建一个滑动条,并指定其所属的窗口、滑动条的名称、最小值、最大值、回调函数
cv2.createTrackbar("Trackbar", "Image", 50, 100, on_trackbar_change)

while True:
    # 等待用户按下任意键退出循环
    key = cv2.waitKey(1)
    if key != -1:
        break

# 关闭窗口
cv2.destroyAllWindows()

在这个例子中,我们通过cv2.createTrackbar创建了一个名为 “Trackbar” 的滑动条,它隶属于名为 “Image” 的窗口,初始值为50,最小值为0,最大值为100。每次滑动条数值发生改变时,都会调用 on_trackbar_change 这个回调函数。

3.2 自定义滑动条回调函数

我们可以根据实际需求,自定义滑动条数值发生变化时的回调函数。例如,在滑动条变化时实时调整图像的亮度、对比度等参数,或者触发其他特定的操作。

import cv2


def on_channel_change(value):
    global image
    # 获取各个滑动条的值
    brightness = cv2.getTrackbarPos("Brightness", "Image") - 50
    red = max(cv2.getTrackbarPos("Red", "Image") - 100, 0)
    green = max(cv2.getTrackbarPos("Green", "Image") - 100, 0)
    blue = max(cv2.getTrackbarPos("Blue", "Image") - 100, 0)

    # 调整图像的亮度和RGB通道
    adjusted_image = cv2.addWeighted(image, 1, image, 0, brightness)
    adjusted_image[:, :, 2] += red
    adjusted_image[:, :, 1] += green
    adjusted_image[:, :, 0] += blue

    # 显示调整后的图像
    cv2.imshow("Image", adjusted_image)


# 创建图像窗口
cv2.namedWindow("Image")

# 创建滑动条,并指定窗口、滑动条名称、初始值、最大值、回调函数
cv2.createTrackbar("Brightness", "Image", 50, 100, on_channel_change)
cv2.createTrackbar("Red", "Image", 100, 200, on_channel_change)
cv2.createTrackbar("Green", "Image", 100, 200, on_channel_change)
cv2.createTrackbar("Blue", "Image", 100, 200, on_channel_change)

# 读取图像
image = cv2.imread("tulips.jpg")

# 在窗口中显示图像
cv2.imshow("Image", image)

# 等待用户按下任意键退出
cv2.waitKey(0)

# 关闭窗口
cv2.destroyAllWindows()

Trackbar

在这个例子中,on_channel_change 函数会在滑动条数值发生变化时被调用,根据数值的变化调整图像的亮度和颜色,并实时在窗口中显示调整后的图像。

通过这些示例,可以更好地理解如何在OpenCV中添加滑动条及其回调函数,从而实现图像处理中的交互操作。这提供了一种灵活的方式,使用户能够通过控件与图像进行动态交互。

四、实现鼠标跟随绘制方框的交互效果

在图像处理中,有时候需要手动标注或选择感兴趣区域。通过结合鼠标事件和按键处理,我们可以实现鼠标跟随绘制方框的交互效果。下面通过一个简单的例子详细介绍如何在OpenCV中实现这一功能。

4.1 代码实现

下面是一个简单的例子,通过OpenCV实现鼠标跟随绘制方框的功能。代码中还包含了撤销上一个框线的操作。

import cv2

drawing = False
start_point = (-1, -1)
rectangles = []  # 存储绘制的框线信息的列表


def mouse_callback(event, x, y, flags, param):
    global drawing, start_point
    # 检测Ctrl键状态
    ctrl_pressed = flags & cv2.EVENT_FLAG_CTRLKEY == cv2.EVENT_FLAG_CTRLKEY

    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        start_point = (x, y)
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        if ctrl_pressed:
            # 如果按下Ctrl键,画蓝色的框线
            cv2.rectangle(image, start_point, (x, y), (255, 0, 0), 2)
            rectangles.append(((start_point[0], start_point[1]), (x, y), (255, 0, 0)))
        else:
            # 否则,画绿色的框线
            cv2.rectangle(image, start_point, (x, y), (0, 255, 0), 2)
            rectangles.append(((start_point[0], start_point[1]), (x, y), (0, 255, 0)))
        cv2.imshow("Image", image)
    elif event == cv2.EVENT_MOUSEMOVE:
        # 清空图像
        image_temp = image.copy()
        # 灰色横线
        cv2.line(image_temp, (x, 0), (x, image.shape[0]), (127, 127, 127), 1, cv2.LINE_AA)
        # 灰色竖线
        cv2.line(image_temp, (0, y), (image.shape[1], y), (127, 127, 127), 1, cv2.LINE_AA)

        if drawing:
            # 根据Ctrl键状态画蓝色或绿色的框线
            if ctrl_pressed:
                cv2.rectangle(image_temp, start_point, (x, y), (255, 0, 0), 2)
            else:
                cv2.rectangle(image_temp, start_point, (x, y), (0, 255, 0), 2)

        cv2.imshow("Image", image_temp)


def undo_last_rectangle():
    global rectangles, image
    if rectangles:
        # 撤销上一个框线
        rectangles.pop()
        # 清空图像
        image = cv2.imread("tulips.jpg")
        # 重新绘制之前的所有框线
        for rect_info in rectangles:
            cv2.rectangle(image, rect_info[0], rect_info[1], rect_info[2], 2)
        cv2.imshow("Image", image)


# 创建图像窗口
cv2.namedWindow("Image")

# 设置鼠标回调函数
cv2.setMouseCallback("Image", mouse_callback)

# 读取图像
image = cv2.imread("tulips.jpg")

# 在窗口中显示图像
cv2.imshow("Image", image)

while True:
    key = cv2.waitKey(0)

    if key == 27:  # 退出键
        break
    elif key == ord('z') or key == ord('Z'):  # 按下Z键
        undo_last_rectangle()

# 关闭窗口
cv2.destroyAllWindows()

4.2 代码解析

  1. 鼠标事件处理: mouse_callback 函数处理鼠标事件,包括鼠标按下、抬起和移动事件。在按下左键时,标记开始绘制;抬起左键时,停止绘制,并根据Ctrl键状态选择画绿色或蓝色框线;在移动过程中,显示灰色的辅助线。

  2. 撤销操作: undo_last_rectangle 函数用于撤销上一个绘制的框线。它会清空图像并重新绘制之前所有的框线。

  3. 主循环: 主循环监听键盘按键事件,按下 “Z” 键时执行撤销操作,按下 “ESC” 键时退出循环。

4.3 运行代码

在弹出的图像窗口中,可以通过鼠标绘制绿色或蓝色的框线,按下 “Z” 键撤销上一个框线,按下 “ESC” 键退出程序。

这个例子演示了如何结合鼠标事件和键盘事件,实现一个简单的交互式图像标注工具。我们可以根据实际需求扩展这个例子,添加更多的交互功能。

画框线

五、自由调节窗口图像的尺寸

在图像处理和计算机视觉应用中,有时候需要对图像窗口进行自由调节,以便更好地查看细节或全局图像。通过监听鼠标事件,我们可以实现自由调节窗口图像尺寸的效果。以下是一个使用OpenCV的简单例子,演示了如何通过鼠标事件实现窗口图像尺寸的自由调节。

5.1 代码实现

import cv2

resizing = False
window_name = "Image"

def mouse_callback(event, x, y, flags, param):
    global resizing

    if event == cv2.EVENT_LBUTTONDOWN:
        resizing = True

    elif event == cv2.EVENT_LBUTTONUP:
        resizing = False

    elif event == cv2.EVENT_MOUSEMOVE:
        if resizing:
            # 获取窗口的位置和大小
            rect = cv2.getWindowImageRect(window_name)
            win_x, win_y, win_width, win_height = rect

            # 判断鼠标是否在窗口的边缘
            if win_x < x < win_x + win_width and win_y < y < win_y + win_height:
                cv2.resizeWindow(window_name, x - win_x, y - win_y)


# 创建图像窗口
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)

# 设置鼠标回调函数
cv2.setMouseCallback(window_name, mouse_callback)

# 读取图像
image = cv2.imread("tulips.jpg")

# 在窗口中显示图像
cv2.imshow(window_name, image)

# 设置窗口的初始大小为图像的大小
cv2.resizeWindow(window_name, image.shape[1], image.shape[0])

# 等待用户按下任意键退出
cv2.waitKey(0)

# 关闭窗口
cv2.destroyAllWindows()

5.2 代码解释

  1. 鼠标事件处理: mouse_callback 函数用于处理鼠标事件,包括按下左键、抬起左键和鼠标移动。当鼠标按下左键时,设置 resizing 为 True;当抬起左键时,设置 resizing 为 False。在鼠标移动过程中,如果 resizing 为 True,则获取窗口的位置和大小,并根据鼠标位置调整窗口大小。

  2. 创建图像窗口: 使用 cv2.namedWindow 创建一个图像窗口,并指定窗口名为 “Image”,设置窗口标志为 cv2.WINDOW_NORMAL,这样窗口大小可以被调整。

  3. 设置鼠标回调函数: 使用 cv2.setMouseCallback 设置鼠标回调函数,即上述的 mouse_callback 函数。

  4. 显示图像和设置初始窗口大小: 读取图像,使用 cv2.imshow 在窗口中显示图像,并通过 cv2.resizeWindow 设置窗口的初始大小为图像的大小。

5.3 运行代码

在弹出的图像窗口中,我们可以通过按下左键并拖动鼠标自由调节窗口的大小。这种交互式的窗口调节方式对于查看大尺寸图像或处理细节较多的图像非常有用。

调整窗口

六、中文显示乱码问题

在图像处理中,有时候我们需要在图像上显示中文字符。为了在OpenCV中实现中文显示,我们需要确保系统的字体支持中文。

6.1 实现步骤

  1. 创建一个空白图像
    首先,我们创建一个空白图像,以便后续在图像上添加中文字符。
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont

# 创建一个空白图像
height, width, _ = 300, 500, 3
image = np.ones((height, width, 3), np.uint8) * 255
  1. 设置中文字体
    选择一个支持中文的字体,这里以宋体为例。我们需要替换 font_path 变量为本地系统中的字体文件路径,确保字体文件支持中文。
    如果没有字体文件,还需要自行下载字体文件。
# 设置中文字体
font_path = r"C:\Windows\Fonts\simsun.ttc"  # 替换为本地的字体文件路径
font_size = 30
font = ImageFont.truetype(font_path, font_size)
  1. 在图像上添加中文字符
    使用 PIL 库来在图像上添加中文字符。在这个例子中,我们添加了一个简单的中文字符 “你好,OpenCV!”。
# 在图像上添加中文字符
image_pil = Image.fromarray(image)
draw = ImageDraw.Draw(image_pil)
text = "你好,OpenCV!"
text_position = (50, 150)
text_color = (0, 0, 0)  # 黑色
draw.text(text_position, text, font=font, fill=text_color)
  1. 转换回OpenCV图像格式并显示
    PIL 图像格式转换回OpenCV格式,并通过OpenCV显示图像。
# 转换回OpenCV图像格式
image = np.array(image_pil)

# 显示图像
cv2.imshow("Chinese Text", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.2 代码实现

以下是一个简单的例子,演示了如何在OpenCV中显示中文字符。

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

# 创建一个空白图像
height, width, _ = 300, 500, 3
image = np.ones((height, width, 3), np.uint8) * 255

# 设置中文字体
font_path = r"C:\Windows\Fonts\simsun.ttc"  # 替换为本地的字体文件路径
font_size = 30
font = ImageFont.truetype(font_path, font_size)

# 在图像上添加中文字符
image_pil = Image.fromarray(image)
draw = ImageDraw.Draw(image_pil)
text = "你好,OpenCV!"
text_position = (50, 150)
text_color = (0, 0, 0)  # 黑色
draw.text(text_position, text, font=font, fill=text_color)

# 转换回OpenCV图像格式
image = np.array(image_pil)

# 显示图像
cv2.imshow("Chinese Text", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

显示中文


总结

通过这篇文章,我们快速入门了OpenCV的窗口交互功能。从鼠标和键盘操作到窗口控件的添加,我们探索了多种交互方式,并通过实例演示了如何实现调整图像亮度和颜色、鼠标跟随绘制绿色框、自由调节窗口图像尺寸以及中文显示。
希望这些简单而实用的示例能够更好地理解和运用OpenCV的窗口交互功能。

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

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

相关文章

坐标系下的运动旋量转换

坐标系下的运动旋量转换 文章目录 坐标系下的运动旋量转换前言一、运动旋量物体运动旋量空间运动旋量 二、伴随变换矩阵三、坐标系下运动旋量的转换四、力旋量五、总结参考资料 前言 对于刚体而言&#xff0c;其角速度可以写为 ω ^ θ ˙ \hat {\omega} \dot \theta ω^θ˙&…

Linux|僵死进程

1.僵死进程产生的原因或者条件: 什么是僵死进程? 当子进程先于父进程结束,父进程没有获取子进程的退出码,此时子进程变成僵死进程. 简而言之,就是子进程先结束,并且父进程没有获取它的退出码; 那么僵死进程产生的原因或者条件就是:子进程先于父进程结束,并且父进程没有获取…

从一到无穷大 #19 TagTree,倒排索引入手是否是优化时序数据库查询的通用方案?

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 文章主旨时序数据库查询的一般流程扫描维度聚合时间聚合管控语句 TagTree整体结构索引…

lv11 嵌入式开发 ARM指令集中(伪操作与混合编程) 7

目录 1 伪指令 2 伪操作 3 C和汇编的混合编程 4 ATPCS协议 1 伪指令 本身不是指令&#xff0c;编译器可以将其替换成若干条等效指令 空指令NOP 指令LDR R1, [R2] 将R2指向的内存空间中的数据读取到R1寄存器 伪指令LDR R1, 0x12345678 R1 0x12345678 LDR伪指令可以将任…

本地私域线上线下 线上和线下的小程序

私域商城是一种新型的零售模式&#xff0c;它将传统的线下实体店与线上渠道相结合&#xff0c;通过会员、营销、效率等方式&#xff0c;为消费者提供更加便利和高效的购物体验。私域商城的发展趋势表明&#xff0c;它将成为未来零售业的重要模式&#xff0c;引领零售业的创新和…

各类语言真实性能比较列表

这篇文章是我所做或将要做的所有真实世界性能比较的索引。如果你对想要看到的其他真实世界案例有建议&#xff0c;请在评论中添加。 用例 1 — JWT 验证 & MySQL 查询 该用例包括&#xff1a; 从授权头部获取 JWT验证 JWT 并从声明中获取电子邮件使用电子邮件执行 MySQL…

数据结构:红黑树的插入实现(C++)

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》 文章目录 一、红黑树二、红黑树的插入三、代码实现总结 一、红黑树 红黑树的概念&#xff1a; 红黑树是一颗二叉搜索树&#xff0c;但在每个节点上增加一个存储位表示节点的颜色&…

Android图片涂鸦,Kotlin(1)

Android图片涂鸦&#xff0c;Kotlin&#xff08;1&#xff09; import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Path import android.graphics.PointF import android.…

改进YOLOv8:结合ODConv构成C2f_ODConv:即插即用的动态卷积/可轻量化

🗝️YOLOv8实战宝典--星级指南:从入门到精通,您不可错过的技巧   -- 聚焦于YOLO的 最新版本, 对颈部网络改进、添加局部注意力、增加检测头部,实测涨点 💡 深入浅出YOLOv8:我的专业笔记与技术总结   -- YOLOv8轻松上手, 适用技术小白,文章代码齐全,仅需 …

常见树种(贵州省):003柏类

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、柏木 …

创新案例|云服务平台HashiCorp是如何构建开源社区实现B2B增长飞轮

社区文化是HashiCorp企业文化的重要组成部分。虽然众多公司声称自己是社区驱动&#xff0c;但实际付诸行动的很少。与众不同的是&#xff0c;HashiCorp从一开始就将社区视为战略方针的核心&#xff0c;这也影响和塑造了公司今天的发展方向。社区不仅是执行策略之一&#xff0c;…

卷积神经网络(CNN)天气识别

文章目录 前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;我的环境&#xff1a; 2. 导入数据3. 查看数据 二、数据预处理1. 加载数据2. 可视化数据3. 再次检查数据4. 配置数据集 三、构建CNN网络四、编译五、训练模型六、模型评估 前期工作 1. 设置GP…

SDUT OJ《算法分析与设计》贪心算法

A - 汽车加油问题 Description 一辆汽车加满油后可行驶n公里。旅途中有若干个加油站。设计一个有效算法&#xff0c;指出应在哪些加油站停靠加油&#xff0c;使沿途加油次数最少。并证明算法能产生一个最优解。 对于给定的n和k个加油站位置&#xff0c;计算最少加油次数。 I…

uniapp 微信小程序登录 新手专用 引入即可

预览 第一步导入插件 在引入的页面的登录按钮下拷贝一下代码 <template><view class"content"><button type"primary" click"login">微信登录</button></view><TC-WXlogin :wxloginwxlogin /> </templ…

【Java 进阶篇】Ajax 入门:打开前端异步交互的大门

欢迎来到前端异步交互的世界&#xff01;在这篇博客中&#xff0c;我们将深入探讨 Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;&#xff0c;这是一项能够让你的网页在不刷新的情况下与服务器进行数据交互的技术。无论你是刚刚踏入前端开发的小白&#xff0c;…

python-opencv 培训课程作业

python-opencv 培训课程作业 作业一&#xff1a; 第一步&#xff1a;读取 res 下面的 flower.jpg&#xff0c;读取彩图&#xff0c;并用 opencv 展示 第二步&#xff1a;彩图 -> 灰度图 第三步&#xff1a;反转图像&#xff1a;最大图像灰度值减去原图像&#xff0c;即可得…

C语言——2.安装并使用VS

文章目录 1.编译器是什么2.编译器的选择2.1.VS2019/2022 的初步了解2.2.为什么不选择其他编译器呢&#xff1f; 3.编译器的安装过程&#xff08;保姆级别教学&#xff09;3.1.检查电脑版本3.2.下载安装包3.3.选择安装选项3.4.重启电脑3.5.创建账户登录3.6.颜色配置3.7.VS&#…

「Verilog学习笔记」根据状态转移图实现时序电路

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 这是一个典型的米利型状态机。三段式即可解决。 米利型状态机&#xff1a;即输出不仅和当前状态有关&#xff0c;也和输入有关。 其中ST0&#xff0c;ST1&#xff0c;ST3的…

力扣刷题篇之位运算

系列文章目录 目录 系列文章目录 前言 一、位运算的基本运算 二、位运算的技巧 三、布隆过滤器 总结 前言 本系列是个人力扣刷题汇总&#xff0c;本文是数与位。刷题顺序按照[力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 - 力扣&#xff08;LeetCode&#xff0…

大反转!OpenAI董事会辞职,求奥特曼重返OpenAI?「奥特曼24小时流放」大揭秘...

大家好&#xff0c;我是二狗。 想必大家昨天都被Sam Altman被董事会解雇的事情刷屏了。 然而才仅仅过去一天&#xff0c;OpenAI 董事会就反悔了&#xff01;正和Sam Altman 商量让他重返CEO职位。 这一反转和Altman被炒鱿鱼一样突然&#xff0c;凄凄惨惨真真假假真真&#x…