利用OpenCV根据图片识别环境的亮度

news2024/9/24 9:17:20

一、前言

在当代数字化转型的浪潮中,计算机视觉技术无疑占据了举足轻重的地位,其应用范围之广,影响力之深,已成为推动社会进步的关键力量之一。而OpenCV,作为计算机视觉领域的佼佼者,凭借其卓越的性能与广泛的兼容性,为开发者提供了强大的工具集,助力其实现复杂视觉任务的高效处理。

环境亮度识别,实质上是一项要求计算机系统能够精准分析并量化图像中光照强度的技术。要求计算机能够理解并量化人类视觉系统对光线变化的感知,进而做出相应的判断和反应。无论是智能照明系统中的自动调光,还是自动驾驶汽车在复杂光照条件下的安全导航,亦或是安防监控中对异常光源的即时警报,这一技术都扮演着至关重要的角色。它不仅提高了自动化系统的效率和可靠性,还极大地丰富了人机交互的方式,让机器能够更加“善解人意”。

例如,在智能家居系统中,自动调节室内光线以适应不同的活动需求或节能目的;在智能交通系统中,动态调整道路照明以应对天气变化和车流量波动;在增强现实领域,实时调整虚拟内容的显示效果以匹配真实世界的光照条件,这些都是环境亮度识别技术需要用到的地方。。

OpenCV,作为一款开源的计算机视觉库,因其强大的功能和广泛的适用性,成为了实现环境亮度识别的理想工具。OpenCV不仅提供了丰富的图像处理函数,还支持多种图像分析算法,这使得开发者能够轻松地从图像中提取亮度信息,并将其转化为可操作的数据。通过加载一张图片,利用OpenCV的图像处理能力,可以计算出图片中亮度的分布情况,进而得到一个反映环境亮度水平的百分比值。

本文章介绍如何利用OpenCV加载一张图片,运用OpenCV库内置的图像处理技术,识别并计算图片中的亮度百分比。

image-20240715145237647

二、OpenCV开发环境安装

【1】OpenCV库下载(官网)

OpenCV是开源的计算机视觉、机器学习软件库,其图片处理的功能非常强大,并且速度很快。 作为目标检测功能,OpenCV里本身就自带了很多的模型,比如: 人眼检测、鼻子检测、嘴巴检测、人脸检测、人体检测、猫脸检测等等,下载完OpenCV,就能直接进行图像识别测试体验,并且OpenCV也可以直接调用YOLO的模型,精确识别各种物体,yolo v3 里自带的模型文件可以精确识别常见的很多物体: 比如: 狗、汽车、自行车、人体、书本、手机等等。

OpenCV下载地址:https://opencv.org/releases/page/3/

目前最新的版本是4.3,那么就下载最新的版本。

image-20230906101920240

image-20230906102004369

下载下来是一个exe文件,双击就可以安装,实际就是解压,可以选择解压的路径,解压出来的文件包含源文件、库文件一大堆,比较大,可以直接放在一个固定的目录,后面程序里直接填路径来调用即可。 这个下载下来的库文件里只包含了X64的库,适用于MSVS 64位编译器。

image-20230906102712398

解压完成。

image-20230906103311462

解压后在build目录下看到有VC14和VC15的目录。这表示什么含义呢?

OpenCV VC14和VC15的区别在于它们所使用的编译器版本不同。VC14使用的是Visual Studio 2015的编译器,而VC15使用的是Visual Studio 2017的编译器。这意味着VC15可以利用更先进的编译器技术,从而提高代码的性能和效率。此外,VC15还支持更多的C++11和C++14特性,使得开发更加方便和灵活。

image-20230906103633870

解释说明:

VC11,Visual Studio 2012编译器

VC14,Visual Studio 2015编译器

VC15,Visual Studio 2017编译器

- VC11构建需要安装Visual Studio 2012 x86或x64的Visual C ++ Redistributable

- VC14构建需要安装Visual Studio 2015 x86或x64的Visual C ++ Redistributable

- VC15构建需要安装Visual Studio 2017 x64或x86的Visual C ++ Redistributable

bin目录下的运行库需要拷贝到生成的应用程序目录下。

image-20230906110606683

【2】MinGw编译器

如果想要使用MinGw编译器编译,可以从这里 https://github.com/huihut/OpenCV-MinGW-Build 下载对应的OpenCV库进行使用。
GitHub的地址在CodeChina有镜像,可以从这里去下载,速度比较快:gitcode.net/mirrors/hui…
打开链接后,自己去选择适合自己编译器的版本,我的MinGW是730刚好就使用下面这个版本。

image-20230210093217258

下面分别介绍VS2017 64位编译器和MinGW 32位编译器如何引用OpenCV的库。

(1)MSVC 64位编译器–QT的xx.pro工程文件里的写法

INCLUDEPATH += C:/opencv/build/include\
INCLUDEPATH += C:/opencv/build/include/opencv\
INCLUDEPATH += C:/opencv/build/include/opencv2

LIBS += -LC:/opencv/build/x64/vc14/lib\
          -lopencv_world347d
LIBS += -LC:/opencv/build/x64/vc14/lib\
          -lopencv_world347

(2)MinGW 32位编译器–QT的xx.pro工程文件里的写法

INCLUDEPATH+=C:/OpenCV-MinGW-Build-OpenCV-3.4.7/include \
             C:/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv \
             C:/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv2
LIBS+=C:/OpenCV-MinGW-Build-OpenCV-3.4.7/x86/mingw/bin/libopencv_*.dll

工程编程成功之后,需要将OpenCV对应的dll文件拷贝到exe同级目录,否则运行时找不到dll会导致程序异常结束。 这些dll文件就是在OpenCV的bin目录下。

OpenCV自带的模型文件在 C:\opencv\sources\data\haarcascades_cuda 这个目录下。

image-20230210093540732

这个就是人脸检测模型文件:

image-20230210093523094

三、实现代码

3.1 识别亮度(C++)

开发环境:在Windows下安装一个VS即可。我当前采用的版本是VS2020。

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

// 计算亮度百分比的函数
double calculateBrightnessPercentage(Mat image) {
    // 将图像转换为灰度图
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // 计算总像素数
    int totalPixels = grayImage.rows * grayImage.cols;

    // 计算亮度较高的像素数(假设亮度阈值为200)
    int brightPixels = 0;
    for (int i = 0; i < grayImage.rows; ++i) {
        for (int j = 0; j < grayImage.cols; ++j) {
            if (grayImage.at<uchar>(i, j) > 200) { // 可根据需要调整阈值
                brightPixels++;
            }
        }
    }

    // 计算亮度百分比
    double percentage = (static_cast<double>(brightPixels) / totalPixels) * 100.0;
    return percentage;
}

int main() {
    // 加载图像
    Mat image = imread("path_to_your_image.jpg");
    
    if (image.empty()) {
        cout << "无法打开或找到图像" << endl;
        return -1;
    }

    // 计算亮度百分比
    double brightnessPercentage = calculateBrightnessPercentage(image);

    // 输出亮度百分比
    cout << "亮度百分比: " << brightnessPercentage << "%" << endl;

    return 0;
}

(1)头文件和命名空间:包括必要的OpenCV头文件 (opencv2/opencv.hpp),使用 cvstd 命名空间以便于调用。

(2)calculateBrightnessPercentage 函数

  • 使用 cvtColor 将输入图像转换为灰度图。
  • 计算图像中总像素数。
  • 统计像素灰度值高于设定阈值(本例中为200)的像素数。
  • 计算亮度百分比,即高亮像素数占总像素数的百分比。

(3)main 函数

  • 使用 imread 从指定路径加载图像。
  • 检查图像是否成功加载。
  • 调用 calculateBrightnessPercentage 函数计算图像的亮度百分比。
  • 输出计算得到的亮度百分比。

3.2 识别亮度(Python)

以下是使用Python和OpenCV计算图像亮度百分比的代码示例:

import cv2
import numpy as np

# 计算亮度百分比的函数
def calculate_brightness_percentage(image):
    # 转换为灰度图像
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 计算总像素数
    total_pixels = gray_image.shape[0] * gray_image.shape[1]

    # 计算亮度较高的像素数(假设亮度阈值为200)
    bright_pixels = np.sum(gray_image > 200)  # 可根据需要调整阈值

    # 计算亮度百分比
    percentage = (bright_pixels / total_pixels) * 100.0
    return percentage

def main():
    # 加载图像
    image = cv2.imread('path_to_your_image.jpg')

    if image is None:
        print("无法打开或找到图像")
        return

    # 计算亮度百分比
    brightness_percentage = calculate_brightness_percentage(image)

    # 输出亮度百分比
    print(f"亮度百分比: {brightness_percentage}%")

if __name__ == "__main__":
    main()

(1)函数 calculate_brightness_percentage

  • 使用 cv2.cvtColor 将输入图像转换为灰度图。
  • 计算图像中总像素数。
  • 使用 NumPy 条件判断 gray_image > 200 来统计亮度较高的像素数(可以根据需要调整阈值 200)。
  • 计算亮度百分比,即高亮像素数占总像素数的百分比。

(2)main 函数

  • 使用 cv2.imread 从指定路径加载图像。
  • 检查图像是否成功加载。
  • 调用 calculate_brightness_percentage 函数计算图像的亮度百分比。
  • 输出计算得到的亮度百分比。

3.3 颜色分类识别(C++)

开发环境:在Windows下安装一个VS即可。我当前采用的版本是VS2020。

下面是使用OpenCV(C++)加载一张图片,并识别出黑、白、红、橙、黄、绿、青、蓝、紫等颜色的占比的完整代码示例:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

// 定义颜色的阈值范围(HSV颜色空间)
const int MIN_H_RED = 0;
const int MAX_H_RED = 10;
const int MIN_H_ORANGE = 11;
const int MAX_H_ORANGE = 25;
const int MIN_H_YELLOW = 26;
const int MAX_H_YELLOW = 34;
const int MIN_H_GREEN = 35;
const int MAX_H_GREEN = 85;
const int MIN_H_CYAN = 86;
const int MAX_H_CYAN = 105;
const int MIN_H_BLUE = 106;
const int MAX_H_BLUE = 130;
const int MIN_H_PURPLE = 131;
const int MAX_H_PURPLE = 160;

// 计算颜色比例的函数
void calculate_color_percentages(Mat image) {
    Mat hsvImage;
    cvtColor(image, hsvImage, COLOR_BGR2HSV);

    // 初始化颜色像素统计变量
    int totalPixels = hsvImage.rows * hsvImage.cols;
    int blackPixels = 0, whitePixels = 0;
    int redPixels = 0, orangePixels = 0, yellowPixels = 0;
    int greenPixels = 0, cyanPixels = 0, bluePixels = 0, purplePixels = 0;

    // 遍历图像像素
    for (int i = 0; i < hsvImage.rows; ++i) {
        for (int j = 0; j < hsvImage.cols; ++j) {
            Vec3b pixel = hsvImage.at<Vec3b>(i, j);
            int hue = pixel[0]; // 色调

            // 根据色调范围判断颜色
            if (hue >= MIN_H_RED && hue <= MAX_H_RED) {
                redPixels++;
            } else if (hue >= MIN_H_ORANGE && hue <= MAX_H_ORANGE) {
                orangePixels++;
            } else if (hue >= MIN_H_YELLOW && hue <= MAX_H_YELLOW) {
                yellowPixels++;
            } else if (hue >= MIN_H_GREEN && hue <= MAX_H_GREEN) {
                greenPixels++;
            } else if (hue >= MIN_H_CYAN && hue <= MAX_H_CYAN) {
                cyanPixels++;
            } else if (hue >= MIN_H_BLUE && hue <= MAX_H_BLUE) {
                bluePixels++;
            } else if ((hue >= 0 && hue < MIN_H_RED) || (hue > MAX_H_PURPLE && hue <= 179)) {
                purplePixels++;
            }
        }
    }

    // 计算颜色百分比
    double percentageBlack = (static_cast<double>(blackPixels) / totalPixels) * 100.0;
    double percentageWhite = (static_cast<double>(whitePixels) / totalPixels) * 100.0;
    double percentageRed = (static_cast<double>(redPixels) / totalPixels) * 100.0;
    double percentageOrange = (static_cast<double>(orangePixels) / totalPixels) * 100.0;
    double percentageYellow = (static_cast<double>(yellowPixels) / totalPixels) * 100.0;
    double percentageGreen = (static_cast<double>(greenPixels) / totalPixels) * 100.0;
    double percentageCyan = (static_cast<double>(cyanPixels) / totalPixels) * 100.0;
    double percentageBlue = (static_cast<double>(bluePixels) / totalPixels) * 100.0;
    double percentagePurple = (static_cast<double>(purplePixels) / totalPixels) * 100.0;

    // 输出颜色百分比
    cout << "黑色百分比: " << percentageBlack << "%" << endl;
    cout << "白色百分比: " << percentageWhite << "%" << endl;
    cout << "红色百分比: " << percentageRed << "%" << endl;
    cout << "橙色百分比: " << percentageOrange << "%" << endl;
    cout << "黄色百分比: " << percentageYellow << "%" << endl;
    cout << "绿色百分比: " << percentageGreen << "%" << endl;
    cout << "青色百分比: " << percentageCyan << "%" << endl;
    cout << "蓝色百分比: " << percentageBlue << "%" << endl;
    cout << "紫色百分比: " << percentagePurple << "%" << endl;
}

int main() {
    // 加载图像
    Mat image = imread("path_to_your_image.jpg");

    if (image.empty()) {
        cout << "无法打开或找到图像" << endl;
        return -1;
    }

    // 计算颜色比例
    calculate_color_percentages(image);

    return 0;
}

3.4 颜色分类识别(python)

以下是相应的Python版本代码,用于加载图像并计算黑、白、红、橙、黄、绿、青、蓝、紫颜色的占比:

import cv2
import numpy as np

# 定义颜色的阈值范围(HSV颜色空间)
COLOR_THRESHOLDS = {
    'black': ([0, 0, 0], [180, 255, 30]),     # 黑色
    'white': ([0, 0, 231], [180, 18, 255]),   # 白色
    'red': ([0, 43, 46], [10, 255, 255]),     # 红色
    'orange': ([11, 43, 46], [25, 255, 255]), # 橙色
    'yellow': ([26, 43, 46], [34, 255, 255]), # 黄色
    'green': ([35, 43, 46], [85, 255, 255]),  # 绿色
    'cyan': ([86, 43, 46], [105, 255, 255]),  # 青色
    'blue': ([106, 43, 46], [130, 255, 255]), # 蓝色
    'purple': ([131, 43, 46], [160, 255, 255]) # 紫色
}

# 计算颜色比例的函数
def calculate_color_percentages(image):
    hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

    # 初始化颜色像素统计变量
    total_pixels = hsv_image.shape[0] * hsv_image.shape[1]
    color_percentages = {}

    # 遍历颜色阈值范围
    for color_name, (lower, upper) in COLOR_THRESHOLDS.items():
        lower_np = np.array(lower, dtype=np.uint8)
        upper_np = np.array(upper, dtype=np.uint8)

        # 根据颜色阈值创建掩码
        mask = cv2.inRange(hsv_image, lower_np, upper_np)

        # 计算掩码中白色像素的数量
        num_pixels = cv2.countNonZero(mask)

        # 计算百分比
        percentage = (num_pixels / total_pixels) * 100.0
        color_percentages[color_name] = percentage

    return color_percentages

if __name__ == "__main__":
    # 加载图像
    image_path = 'path_to_your_image.jpg'
    image = cv2.imread(image_path)

    if image is None:
        print(f"无法打开或找到图像:{image_path}")
    else:
        # 计算颜色比例
        percentages = calculate_color_percentages(image)

        # 输出颜色百分比
        for color, percentage in percentages.items():
            print(f"{color}百分比: {percentage:.2f}%")

(1)颜色定义和阈值范围

  • 使用HSV颜色空间来识别颜色,定义了各种颜色的HSV阈值范围。
  • 每个颜色都有一个对应的最小和最大HSV值。

(2)calculate_color_percentages 函数

  • 使用 cv2.cvtColor 将图像从BGR色彩空间转换为HSV色彩空间。
  • 初始化颜色百分比的字典。
  • 针对每种颜色的HSV阈值范围,使用 cv2.inRange 创建颜色掩码。
  • 使用 cv2.countNonZero 计算掩码中非零像素的数量,即符合颜色条件的像素数量。
  • 计算每种颜色在图像中的百分比。

(3)main 函数

  • 加载指定路径的图像。
  • 检查图像是否成功加载。
  • 调用 calculate_color_percentages 函数计算并输出图像中各种颜色的百分比。

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

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

相关文章

强推!必看!!由中国信通院发布的汇聚99个大模型优秀应用案例集!附219页PDF文件下载

2024 年是大模型深入赋能千行百业&#xff0c;融入实体经济&#xff0c;助力科技创新的一年。截至今年5月&#xff0c;我国国产大模型的数量已经超过 300个&#xff0c;预示着大模型在各行业场景的创新应用和深度拓展&#xff0c;对培育新质生产力、高水平赋能新型工业化、推动…

第100+23步 ChatGPT学习:概率校准 Sigmoid Calibration

基于Python 3.9版本演示 一、写在前面 最近看了一篇在Lancet子刊《eClinicalMedicine》上发表的机器学习分类的文章&#xff1a;《Development of a novel dementia risk prediction model in the general population: A large, longitudinal, population-based machine-learn…

java中超级重要的SPI机制

SPI机制是理解各个框架集成的重要思想&#xff0c;只用理解了SPI才能理解框架的集成和扩展。直观的就是SPI机制可以让你更好的理解springboot集成各个扩展。 废话不多说&#xff01;&#xff01; 1.什么是spi机制&#xff1f; Spi机制是java提供的一种服务发现机制&#xff0…

企业常用的10款主流图纸加密软件排行榜|企业图纸防泄密

图纸是企业的重要资产&#xff0c;其安全性直接关系到企业的核心竞争力。下面为大家介绍10款主流的图纸加密软件&#xff0c;每款软件都有其独特的功能和优势&#xff0c;帮助企业有效防止图纸泄密。 1. 安秉图纸加密软件 安秉图纸加密软件是一款专为企业用户设计的图纸加密解…

全球石油巨头哈里伯顿因网络攻击被迫关闭系统

美国能源服务巨头哈里伯顿公司在周五向联邦监管机构提交的文件中表示,在本周遭受网络攻击后,该公司主动关闭了某些系统以“帮助保护它们”。 该公司在提交给美国证券交易委员会的文件中表示,周三该公司获悉“未经授权的第三方获得了其系统某些部分的访问权限”,并正在与外…

如何开启让设备获取到IPv6?

前言 现在许多小伙伴拉的宽带基本上都是光猫进行拨号的。这个就导致很多小伙伴不知道如何让设备获取IPv6。 但好像还有小伙伴分不清光猫拨号和光猫桥接的区别&#xff0c;其实它们的区别就在于让设备直连光猫的网口或者光猫的Wi-Fi&#xff0c;就会出现两种情况&#xff1a; …

实战派六西格玛:培训只是热身,应用才是关键!

在当今竞争激烈的市场环境中&#xff0c;六西格玛作为一套卓越的质量管理策略与工具&#xff0c;其影响力已远远超越了单纯的制造领域&#xff0c;渗透至各行各业的运营管理之中。然而&#xff0c;许多企业在追逐六西格玛光环的过程中&#xff0c;却常常偏离了其核心轨道&#…

中国全球投资追踪相关数据(2005-2023年)

中国全球投资追踪的相关数据可以为了解中国在全球范围内的投资活动提供重要视角。根据美国企业研究所&#xff08;American Enterprise Institute&#xff0c;AEI&#xff09;编制的《中国全球投资追踪》数据库&#xff0c;该数据库详细追踪了2005年至2023年间中国的海外直接投…

wx.updateAppMessageShareData 自定义分享内容安卓无效

记录wx.updateAppMessageShareData 自定义分享内容安卓无效 bug&#xff0c;主要是因为微信公众平台要配置分享的链接域名。 情况微信公众号使用wxjsdk后分享api全都注入成功&#xff0c;自定义分享内容时ios正常安卓分享出去的是当前页面的url。 主要原因在于你自定义这个分享…

在linux 中如何将.c 文件转换为可执行文件

目录 一、引言 二、准备工作 三、编译单个.c 文件 1.预处理 2.编译 3.汇编 4.链接 四、编译多个.c 文件 五、调试和优化 六、总结 一、引言 在 Linux 环境下进行 C 语言编程时&#xff0c;将 .c 文件转换为可执行文件是一个关键的步骤。这个过程涉及到使用编译器和一…

携程:从MySQL迁移OceanBase的数据库发布系统实践

作者简介&#xff1a;杨晓军 现就职于携程的数据库团队&#xff0c;主要负责携程数据库的研发与管理&#xff0c;专注于提升数据库的稳定性。 自分布式关系型数据库OceanBase开源以来&#xff0c;携程已经在线上环境中进行了广泛的应用&#xff0c;取代了原先以MySQL为主力的业…

虚幻5|技能栏优化(1)---优化技能UI,并添加多个技能

一.添加多一个技能格子并进行初始化清楚 1.打开技能UI把原先的事件构造后面的蓝图&#xff0c;全部选中&#xff0c;右键创建一个函数&#xff0c;命名为初始化 2.添加以下两个蓝图&#xff0c;用于清楚技能格子内容 2.在之前&#xff0c;事件构造后面的蓝图&#xff0c;不需…

人工智能是如何预测足球比赛的?看完这篇文章,你就全懂了!AutoPrediction

2024年欧洲杯开赛至今&#xff0c;德叔已经用人工智能预测了小组赛阶段的36场比赛&#xff0c;以及淘汰赛阶段的8场比赛&#xff0c;并且通过在网络上的发文&#xff0c;记录了所有这些比赛的预测结果。这些文章引来了不少朋友的围观&#xff0c;也让很多人对人工智能预测球赛这…

收藏夹里的“小网站”被误报违规不让上怎么办?如何将Chrome和Edge安装到 D 盘(含用户数据),重装系统也不会丢失收藏夹和密码?

当你用国产浏览器访问网站的时候&#xff0c;有时候会显示这个&#xff1a; 如果确实是违规网站&#xff0c;不让访问也没什么&#xff0c;但是很多都是误报啊&#xff0c;你这样直接来个大红横幅&#xff0c;还让人活不&#xff1f; 那遇到这种误报应当怎么办呢&#xff1f;有…

echarts 中 鼠标悬浮上加单位

tooltip: {trigger: "axis",valueFormatter: function (value: any) {return value "℃";},}, 效果&#xff1a;

开放式耳机的优缺点?开放式耳机王者带你一探究竟

盛夏时节&#xff0c;天气越来越热&#xff0c;小伙伴们都在抱怨&#xff0c;实在没法戴口罩了。实际上&#xff0c;大家只关注了呼吸&#xff0c;却忽视了一个问题&#xff0c;其实&#xff0c;我们的耳朵也是要“呼吸”的&#xff0c;闷热的天气里&#xff0c;长时间佩戴入耳…

S2P销讯通-主数据对于客户关系管理系统的重要性

由于业务发展&#xff0c;各大企业的业务系统经历了从无到有&#xff0c;从简单到复杂&#xff0c;从而形成了一个又一个的业务系统&#xff0c;比如OA、HR、CRM、ERP等等。 主数据在客户关系管理系统&#xff08;CRM&#xff09;中扮演着至关重要的角色。主数据是指那些描述企…

SD操作手册

1、创建条件记录 2、创建标准订单/寄售补货订单/寄售发货订单/借贷项凭证/退货订单 3、创建外向交货单 4、开票 创建条件记录-VK11 PR00代表净价 输入销售组织、分销渠道、客户、物料 创建销售订单-VA01 2.1创建标准SO 维护完表头的信息后&#xff0c;双击行项目&#xff…

Python发送多人邮件如何实现高效群发功能?

Python发送多人邮件的教程&#xff1f;怎么使用Python群发邮件&#xff1f; Python&#xff0c;作为一种强大的编程语言&#xff0c;提供了多种库和工具&#xff0c;使得群发邮件变得既简单又高效。AokSend将详细介绍如何使用Python发送多人邮件&#xff0c;并探讨一些提高群发…

wpf prism 《3》 弹窗 IOC

传统的弹窗 这种耦合度高 new 窗体() . Show(); new 窗体() . ShowDialog(); 利用Prism 自动的 IOC 弹窗的 必须 必须 必须 页面控件 弹窗的 必须 必须 必须 页面控件 弹窗的 必须 必须 必须 页面控件 弹窗的 必须 必须 必须 页面控件 弹窗的 必须 必须 必须 页面控件 》》否…