版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
手势识别知识目标技能目标构建和应用图像金字塔:熟练使用OpenCV的pyrDown和pyrUp函数构建高斯金字塔和拉普拉斯金字塔,进行图像的多层次降采样与上采样。选择合适的阈值分割方式实现阈值分割:运用Otsu方法及其他阈值处理技术,对批量图像进行自动化的二值化处理,优化图像分割效果。轮廓特征提取与分析:通过OpenCV函数提取图像轮廓的各类几何特征,并进行可视化展示,增强对图像结构的理解。掌握查找以及绘制凸包和凸缺陷的技能。素质目标
问题解决能力:在面对复杂图像处理任务时,能够分析问题、选择合适的方法与工具,设计合理的解决方案。
自主学习与持续进步:培养自主学习新技术、新方法的能力,保持对图像处理领域最新发展的关注与学习,持续提升专业素养。项目背景手势识别的应用场景已渗透至多个领域,其核心价值在于提供直观、自然的交互方式,当前,手势识别已经广泛应用于各个领域。消费与商业领域:可用于无接触购物无接触购物:消费者可通过手势切换商品展示页面,提升线下零售体验;智能试衣与咨询:结合生成式AI,实现虚拟试衣、美妆试色等个性化服务,优化消费决策流程智能设备与家居控制领域:可用于家电与灯光操控:通过手势调节灯光亮度、开关窗帘或控制空调温度,适用于智能家居场景,可穿戴设备交互:智能手环/手表支持手势接听电话、切换音乐等操作,提升移动设备使用便捷性。交通与车载系统:可用于识别交警指挥手势或行人动作,辅助自动驾驶系统优化路况响应医疗与公共安全领域:可用于无接触操作,手势控制设备可降低交叉感染风险,例如手术室设备操控或病房环境调节娱乐与虚拟交互领域:玩家通过手势直接操作游戏角色动作,增强沉浸感,替代传统手柄输入。任务引入作为一名计算机视觉工程师,您负责设计和开发用于人机交互系统的先进手势识别程序。您的任务是利用图像处理技术,如阈值处理、轮廓检测、凸包和凸缺陷分析,创建一个能够准确识别“石头、剪刀、布”等手势的程序。任务准备要完成该项工作,需要具备以下知识基础:图像金字塔阈值处理图像轮廓谢谢!图像下采样图像金字塔
图像金字塔是一种多尺度图像表示方法,通过逐层降采样和上采样,将图像表示为多个不同分辨率的层次。这种方法不仅可以减少图像处理的计算复杂度,还能在不同的尺度上捕捉图像的全局结构与局部细节。在实际应用中,图像金字塔被广泛用于对象检测、图像融合、图像压缩等任务中。图像金字塔主要分为高斯金字塔和拉普拉斯金字塔两种类型。图像下采样概念
下采样是图像金字塔构建的核心步骤之一,主要用于逐层减少图像的分辨率。下采样在保持图像的主要结构和内容的前提下,通过模糊处理和降尺度操作来降低图像分辨率。这种方法在多尺度分析和对象检测中尤为重要,因为在低分辨率的情况下可以减少数据量并加快计算速度。OpenCV的cv2.pyrDown()函数能够对图像进行下采样处理,生成一个分辨率为原图像四分之一的新图像。在内部实现中,该函数会先对图像进行高斯模糊,减少噪声对降采样的影响,从而保留主要的图像特征。下采样的图像尺寸大致是原图的一半,但其像素数量减少到原来的四分之一。此函数在多层次目标检测、背景提取、图像融合等场景下广泛应用。通过对图像不断下采样,可以形成一个逐层分辨率降低的高斯金字塔。下采样函数OpenCV提供了cv2.pyrDown()函数用于对图像进行降采样,通常将图像的宽度和高度尺寸均缩小为原来的一半。降采样可以减少图像的细节和分辨率,常用于构建图像金字塔。cv2.pyrDown()函数的语法格式如下;dst=cv2.pyrDown(src[,dstsize[,borderType]])
src:输入图像,必须为8位或浮点型的单通道或多通道图像。
dstsize:可选参数,用于设置输出图像的大小,默认情况下输出图像宽度和高度为输入图像的一半。
borderType:边界模式,默认值为cv2.BORDER_DEFAULT。此参数定义边界像素的填充方式,常见选项包括:
(1)cv2.BORDER_CONSTANT:添加常数值的边框。
(2)cv2.BORDER_REPLICATE:复制边界值。
(3)cv2.BORDER_REFLECT:镜像边界值。
dst返回降采样后的图像,其尺寸是原图的1/2。图像下采样函数案例importcv2img=cv2.imread("image//fish.jpg")#读取原始图像down1=cv2.pyrDown(img)#第一次下采样,将图像尺寸缩小为原图的1/4down2=cv2.pyrDown(down1)#第二次下采样,将图像尺寸缩小为第一次下采样的1/4#显示下采样后的各级图像cv2.imshow("img",img)#显示第一次下采样结果cv2.imshow("DownsampledImage2",down1)#显示第二次下采样结果cv2.imshow("DownsampledImage3",down2)#显示第三次下采样结果cv2.waitKey(0)#等待用户按键cv2.destroyAllWindows()#关闭所有窗口【例5.1pyrdown.py】下采样示例。
图像下采样案例
图5.1最大的图片为原图,中间的图像为第一次降采样后的图像,最小的图像为第二次降采样的结果,可见,每次降采样将图像的宽度和高度均变为原来的一半,图像大小变为原来的四分之一。例5.1输出结果谢谢!图像上采样图像上采样概念
上采样是图像金字塔中从低分辨率图像恢复到较高分辨率的一种操作,用于图像复原、重构等任务。OpenCV的cv2.pyrUp()函数可以将图像进行上采样,从而生成一个比原始输入分辨率更高的图像。上采样在增大图像分辨率的同时会插值新像素值,以确保图像在放大后尽量保持细节完整。该操作通常是通过在现有像素之间添加新像素,然后应用高斯模糊来平滑像素间的过渡。需要注意的是,cv2.pyrUp()并不能恢复图像中的细节,而是适合在图像融合、拉普拉斯金字塔重构等任务中保持图像的连续性和一致性。上采样生成的图像会保留输入图像的基本结构,同时放大图像中可见的特征。图像上采样函数OpenCV提供的cv2.pyrUp()函数用于对图像进行上采样,通常将图像宽度和高度尺寸放大到原来的两倍。上采样的操作对图像细节信息进行插值,适合用于金字塔图像的逆向重建。语法格式如下:dst=cv2.pyrDown(src[,dstsize[,borderType]])
src:输入图像,必须为8位或浮点型的单通道或多通道图像。
dstsize:可选参数,用于设置输出图像的大小,默认情况下输出图像宽度和高度为输入图像的两倍。
borderType:边界模式,默认值为cv2.BORDER_DEFAULT。此参数定义边界像素的填充方式,常见选项包括:
(1)cv2.BORDER_CONSTANT:添加常数值的边框。
(2)cv2.BORDER_REPLICATE:复制边界值。
(3)cv2.BORDER_REFLECT:镜像边界值。
dst返回上采样后的图像,其尺寸是原图的2倍。图像上采样案例importcv2img=cv2.imread("image/fish-small.jpg")up1=cv2.pyrUp(img)#第一次上采样,将图像尺寸放大为原图的4倍up2=cv2.pyrUp(up1)#第二次上采样,将图像尺寸放大为第一次上采样的4倍#显示上采样后的各级图像cv2.imshow("img",img)#显示第一次上采样的结果cv2.imshow("up1",up1)#显示第二次上采样的结果cv2.imshow("up2",up2)#显示第三次上采样的结果cv2.waitKey(0)#等待用户按键cv2.destroyAllWindows()#关闭所有窗口【例5.2pyrup.py】上采样示例。1.3上采样函数
图5.2中最小的图像为原图,中间的图像为第一次上采样的结果,右侧的图像为第二次上采样的结果,由图可见,每次上采样图像的宽度和高度均扩大为原来的两倍,图像变为原来的四倍,并且图像效果也越来越模糊。例5.2输出结果谢谢!采样的可逆性研究采样的可逆性研究内容
采样的可逆性是指在图像金字塔处理过程中,图像在降采样后再进行上采样,能否近似地还原到原图像的细节。例5.3展示图像进行下采样后再上采样,比较与原图是否相同。采样的可逆性研究案例importcv2importnumpyasnpimage=cv2.imread('image//fish.jpg')#读取原图image=cv2.resize(image,(240,240))down_image=cv2.pyrDown(image)#下采样up_image=cv2.pyrUp(down_image)#上采样difference=abs(image-up_image)#计算差值cv2.imshow('OriginalImage',image)#显示原图cv2.imshow('DownsampledImage',down_image)#显示下采样的图像cv2.imshow('UpsampledImage',up_image)#显示上采样的图像cv2.imshow('Difference',difference)#显示原图和下采样后又上采样的图像差值cv2.waitKey(0)cv2.destroyAllWindows()【例5.3down_up.jpg】先对图像进行下采样,然后进行上采样,最后将原图减去上采样的结果,查看与原图是否有差别。采样的可逆性研究案例
图5.3(a)是原图,图5.3(b)是下采样的图像,图像大小变为原来的1/4,5.3(c)是对5.3(b)上采样的结果,图像大小和原图一样,图5.3(d)是原图减去下采样又上采样的结果,由图可见,上采样后图像和原图大小虽然一样,但是像素值有区别,说明下采样后又上采样的图像和原图有区别。图5.3例5.3 输出结果(a)
(b)
(c)
(d)谢谢!拉普拉斯金字塔拉普拉斯金字塔概念0201
拉普拉斯金字塔在图像压缩和图像融合任务中也显示出其独特的优势。在图像压缩中,通过仅传输高斯金字塔的低频信息和拉普拉斯金字塔的高频信息,可以在保持图像质量的同时显著减少数据量。而在图像融合过程中,拉普拉斯金字塔能够确保融合后的图像保留源图像的细节特征,使得融合结果更加自然和准确。这些应用不仅展示了拉普拉斯金字塔在图像处理中的广泛适用性,也体现了其在提高图像处理效率和质量方面的重要价值。图5.4展示了拉普拉斯金字塔的构建过程,图中G0为原图,G1为第一次下采样图像,G2为第二次下采样的图,L0为拉普拉斯金字塔第0层,L1为拉普拉斯金字塔第1层,L2为拉普拉斯金字塔第2层。拉普拉斯金字塔的优势
拉普拉斯金字塔是图像处理中一个关键的概念,它作为高斯金字塔的扩展,专门用于捕捉图像的高频信息,即图像的边缘和细节。通过从高斯金字塔的相邻层中减去上采样后的图像,拉普拉斯金字塔能够精确地提取出这些关键的视觉特征。这些特征对于图像的视觉感知至关重要,使得拉普拉斯金字塔在图像重建领域中发挥着不可或缺的作用。它不仅可以帮助恢复图像在压缩或其他处理过程中丢失的细节,还能显著提高重建图像的质量。拉普拉斯金字塔的概念拉普拉斯金字塔原理
图5.4拉普拉斯金字塔构建过程由图5.4可以看出,拉普拉斯金字塔构建过程如下:G1=cv2.pyrDown(G0)G2=cv2.pyrDown(G1)G3=cv2.pyrDown(G2)L0=G0-cv2.pyrUp(G1)L1=G1-cv2.pyrUp(G2)L2=G2-pyrUp(G3)由构建过程可知,拉普拉斯金字塔保留了原图减去下采样再上采样后图像的差值信息。思考:如果要恢复原图,需要如何利用拉普拉斯金字塔?拉普拉斯金字塔构建案例importcv2img=cv2.imread("image//fish.png")G0=imgG1=cv2.pyrDown(G0)#下采样获取G1G2=cv2.pyrDown(G1)#对G1下采样获取G2G3=cv2.pyrDown(G2)#对G2下采样获取G3L0=G0-cv2.pyrUp(G1)#构建拉普拉斯金字塔L0层L1=G1-cv2.pyrUp(G2)#构建拉普拉斯金字塔L1层L2=G2-cv2.pyrUp(G3)#构建拉普拉斯金字塔L2层print("L0.shape=",L0.shape)#输出L0的形状print("L1.shape=",L1.shape)#输出L1的形状print("L2.shape=",L2.shape)#输出L2的形状cv2.imshow("L0",L0)#展示L0cv2.imshow("L1",L1)#展示L1cv2.imshow("L2",L2)#展示L02cv2.waitKey()cv2.destroyAllWindows()【例5.4laplacian.py】拉普拉斯金字塔构建案例。拉普拉斯金字塔案例
图5.5(a)是拉普拉斯金字塔第0层,大小与G0相同,5.5(b)是拉普拉斯金字塔第1层,大小与G1大小相同,5.5(c)是拉普拉斯金字塔第2层,大小与G2相同。(a)L0.shape=(400,400,3)L1.shape=(200,200,3)L2.shape=(100,100,3)(b)(c)利用拉普拉斯金字塔恢复原图案例importcv2importnumpyasnpimg=cv2.imread("image//fish.png")G0=imgG1=cv2.pyrDown(G0)#下采样获取G1L0=G0-cv2.pyrUp(G1)#构建拉普拉斯金字塔L0层G_recover=L0+cv2.pyrUp(G1)#利用拉普拉斯金字塔恢复图像diff=abs(G0-G_recover)#原图减去拉普拉斯金字塔恢复的图像获取差值图像sum_diff=np.sum(diff)#计算差值图像的像素点之和print("差值图像像素点之和={}".format(sum_diff))cv2.imshow("diff",diff)#输出差值图像cv2.waitKey()cv2.destroyAllWindows()【例5.5laplacian_recover.py】利用拉普拉斯金字塔将下采样的图片恢复为原图。
将原图减去利用拉普拉斯金字塔恢复的图像后,得到的差值图像的像素之和等于0,说明差值图像中所有对应像素的差均为0,代表着原图和利用拉普拉斯金字塔恢复的图像完全相同,差值图像如图5.6所示为全黑色。可见,利用拉普拉斯金字塔保留图像细节,可以使图像恢复成原图。图5.6例5.5输出结果利用拉普拉斯金字塔恢复原图案例谢谢!阈值处理阈值处理概述
阈值处理的另一个重要用途是自动化图像分析流程。通过自动选择最佳阈值,例如使用Otsu方法,可以减少人工干预,提高处理速度和效率。这种方法特别适用于需要处理大量图像的场景,如卫星图像分析、视频监控和工业自动化检测。阈值处理不仅是一种简单的图像二值化手段,更是一种强大的工具,它在图像分析的各个阶段都扮演着关键角色,使得图像处理任务更加高效和准确。
阈值处理的应用非常广泛,它不仅能够简化图像内容,还在图像分割、特征提取、目标识别等多个领域发挥重要作用。在图像预处理阶段,阈值处理有助于去除噪声和无关细节,为后续分析打下基础。在特征提取和目标识别中,它能够突出感兴趣的区域,为进一步的分析提供清晰的边界。此外,阈值处理在医学影像分析中也非常重要,常用于突出显示病变区域,辅助医生进行诊断。
阈值处理是图像二值化的基本方法,通过设定一个或多个阈值,将图像像素分为前景和背景。这一过程对于图像分割、特征提取和图像增强等任务至关重要。尤其是Otsu阈值方法,作为一种自动化的全局阈值选择方法,能够根据图像的灰度直方图自动确定最佳分割阈值。例如,设定阈值为127,所有像素值大于127的像素点将被设置为255(白色),而所有像素值小于127的像素点将被设置为0(黑色)。这种处理将一幅灰度图像转换为二值图像,有效地实现了前景和背景的分离。
阈值处理函数OpenCV3.0使用cv2.threshold()函数进行阀值化处理,函数语法格式如下:retval,dst=cv2.threshold(src,thresh,maxval,type)
thresh代表要设置的阀值
maxval代表当type参数为THRESH_BINARY或者THRESH_BINARY_INV类型时要设置的最大值。
type代表阀值分割的类型,具体类型如表5.1所示。表5.1阈值分割的类型
阈值处理函数类型说明cv2.THRESH_BINARY(二值化阈值处理)当像素值大于thresh时取maxval,否则取0cv2.THRESH_BINARY_INV(反二值化阈值处理)当像素值大于thresh时取0,否则取maxvalcv2.THRESH_TRUNC(截断阈值处理)当像素值大于thresh时取thresh,否则取0cv2.THRESH_TOZERO_INV(超阈值零处理)当像素值大于thresh时取0,否则保持像素值不变cv2..THRESH_TOZERO(低阈值零处理)当像素值大于thresh时保持像素值不变,否则取0cv2.THRESH_MASK掩码cv2.THRESH_OTSU标记,使用Otsu算法时的可选阈值参数cv2.THRESH_TRIANGLE标记,使用Triangle算法时的可选阈值参数表5.1阈值分割的类型阈值处理案例-二值化阈值处理importcv2importnumpyasnpimg=np.random.randint(0,256,size=[3,5],dtype=np.uint8)#阈值127,最大值255,类型为二值化阈值处理t,rst=cv2.threshold(img,127,255,cv2.THRESH_BINARY)print("img=\n",img)print("t=",t)print("rst=\n",rst)【例5.6thresh_gray.py】随机生成灰度图像,使用阈值处理函数进行阈值处理,观察输出结果。结果解析
案例中将阈值设置为127,结果可以看出,使用二值化阈值处理,当像素值大于阈值127时,将其设置为255,小于127时,将其设置为0。同学们可以尝试修改type的值观察输出结果。阈值处理案例-二值化阈值处理rst=[[255025500][0255255255255][2550255255255]]img=[[2101152442549][54188207165221][24266139191234]](a)(b)阈值处理案例-对图像进行二值化阈值处理importcv2img=cv2.imread("image/gray_fish.jpg")t,img_binary=cv2.threshold(img,127,255,cv2.THRESH_BINARY)#二值化阈值处理t,img_binary_inv=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)#反二值化阈值处理t,img_trunc=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)#截断阈值化处理t,img_tozero=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)#低阈值零处理cv2.imshow("img",img)cv2.imshow("img_binary",img_binary)cv2.imshow("img_binary_inv",img_binary_inv)cv2.imshow("img_trunc",img_trunc)cv2.imshow("img_tozero",img_tozero)cv2.waitKey()cv2.destroyAllWindows()【例5.7different_thresh.py】将图像gray_fish.jpg进行不同类型的阈值处理,观察输出结果。
图5.7(a)是原图,5.7(b)是二值化阈值处理结果,5.7(c)是反二值化阈值处理结果,5.7(d)是截断阈值处理结果,5.7(e)是低阈值零处理结果,同学们可以根据表5.1阈值分割类型理解输出结果的像素值变化。阈值处理案例-对图像进行阈值处理例5.7输出结果
(a)
(b)
(c)(d)
(e)
谢谢!自适应阈值处理自适应阈值处理概述
上节的阈值处理是由人工指定的阈值,有时图像色彩不均衡,此时如果只使用一个阈值,就无法得到清晰有效的分割结果。自适应阈值处理可以使用变化的阈值完成对图像的阈值处理。在进行阈值处理时,自适应阈值处理的方式通过计算每个像素点周围临近区域的加权平均值获得阈值,并使用该阈值对当前像素点进行阈值处理。与普通的阈值处理方法相比,自适应阈值处理能够更好的处理明暗差异较大的图像。自适应阈值处理函数OpenCV提供了函数cv2.adaptiveThreshold()函数实现自适应阈值处理,语法格式如下:dst=cv2.adaptiveThreshold(src,maxValue,adaptiveMethod,thresholdType,blockSize,C)
dst表示处理结果图像。
src代表要进行处理的原始图像。
adaptiveMethod表示自适应方法。
thresholdType表示阀值处理方法,必须是cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV中的一个。
blockSize表示块大小,表示在计算与阈值时所使用的邻域尺寸,通常是3、5或者7。
C表示常量。自适应阈值处理函数
cv2.adaptiveMethod()用来确定自适应阀值的计算方法,函数包含cv2.ADAPTIVE_THRESH_MEAN_CCV2.ADAPTIVE_THRESH_GAUSSIAN_C两种不同的方法,这两种方法都是逐个像素计算自适应阀值,自适应阀值等于每个像素由参数blockSize所指定邻域的加权平均减去常量C。cv2.ADAPTIVE_THRESH_MEAN_C:邻域所有像素点的权重值是一样的。CV2.ADAPTIVE_THRESH_GAUSSIAN_C:与邻域各像素点到中心点的距离有关,通过高斯方程得到各点的权重值。自适应阈值处理案例importcv2img=cv2.imread("image//girl.jpg")gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#BGR图像转换为灰度图像t1,thd=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)#人工指定阈值为127athdMEAN=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,5)athdGAUS=cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,3,5)cv2.imshow("img",img)cv2.imshow("gray",gray)cv2.imshow("thd",thd)cv2.imshow("athdMEAN",athdMEAN)cv2.imshow("athdGAUS",athdGAUS)cv2.waitKey()cv2.destroyAllWindows()【例5.8thresh_compare.py】分别使用普通的阈值处理和自适应阈值处理对图像girl.jpg进行阈值处理,观察输出结果。自适应阈值处理案例
图5.8(a)是原图,为彩色图像,图5.8(b)是转换为灰度图像的结果,注意阈值处理仅能处理灰度图像,图5.8(c)使用普通阈值处理(指定阈值为127)后的图像,图5.8(d)和5.8(e)分别使用自适应阈值处理的结果,可以看出使用自适应阈值处理比普通阈值处理保留了更多的细节。
(a)
(b)(c)
(d)
(e)
谢谢!Otsu阈值处理Otsu阈值处理概述
在使用函数cv2.thresh()进行阀值处理时,通常需要手动设置一个阈值,这个阈值用于将图像的像素分为前景和背景。在图像灰度级分布均匀的情况下,将阈值设置为127可能是一个合理的选择,因为这样的设置能够将图像的灰度值分为两个较为均衡的部分。然而,这种手动设定阈值的方法存在明显的局限性。当图像的灰度级分布不均衡时,固定阈值可能导致不准确的分割,例如在以下图像像素值的情况下,如果仍然使用127分割阈值,导致图像为全黑色。
[[120125125120]
[120110115110]
[100123115116]]
图像像素值示例Otsu阈值处理概述
为了解决这一问题,我们引入了Otsu阈值方法,这是一种自适应阈值技术,能够自动从图像的灰度直方图中确定最佳的阈值。Otsu方法的核心在于最大化类间方差,即寻找一个阈值,使得前景和背景之间的差异最大化。这种方法的优势在于它不需要人为指定阈值,而是根据图像的灰度分布自动确定最佳分割点,特别适用于灰度级分布不均匀的图像。Otsu方法能够自动适应图像的特性,提供更准确的分割结果,避免因手动选择不当阈值而导致的图像分割错误。在图像的光照条件不均匀或者目标和背景对比度不高的情况下,Otsu方法的自动化特性减少了人工干预,提高了处理效率和结果的准确性,使其成为图像分割领域中一个非常有价值的工具。在OpenCV中,通过在函数cv2.threshold()中对参数type的类型传递一个参数cv2.THRESH_OTSU即可实现Otsu方式的分割。在使用Otsu方法时,要把阀值设置为0。函数会自动寻找最有阀值。t,Otsu=cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
type增加了一个参数cv2.THRESH_OTSU
设定的阀值为0
返回值t是OTSU方法得到的最优阀值Otsu阈值处理案例importcv2img=cv2.imread("image//fish.jpg")gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)t1,thd=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)t2,otsu=cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)print("指定阈值=",t1)print("OTSU阈值=",t2)cv2.imshow("img",img)cv2.imshow("thd",thd)cv2.imshow("otus",otsu)cv2.waitKey()cv2.destroyAllWindows()【例5.9thresh_otsu.py】分别使用指定阈值和使用OTSU进行阈值处理,比较输出结果。Otsu阈值处理案例
指定阈值为127,自动获取的阈值为178,图5.9(a)是原图,5.9(b)是指定阈值处理结果,5.9(c)是自动阈值处理结果,可见,自动获取的阈值保留了更多的细节。例5.9输出结果
(a)
(b)(c)谢谢!图像轮廓图像轮廓
图像轮廓检测是图像处理中的重要任务,能帮助识别图像中对象的边界、形状和结构。轮廓通常用于对象分割和形状分析。
轮廓是图像中的闭合边界,用于区分图像的前景和背景。通过二值化处理和轮廓查找,可以获得图像中的对象轮廓,便于后续的形状分析、特征提取和目标检测。查找图像轮廓的函数
OpenCV中的函数
cv2.findContours()用于在二值化图像中检测轮廓。它的主要作用是识别出图像中的连通区域,并将这些区域的边界点集合起来,形成轮廓的点集。这个函数返回两个值:contours和hierarchy,函数语法格式如下:contours,hierarchy=cv2.findContours(image,mode,method)
image:二值化图像。
mode:轮廓的模式。cv2.RETR_EXTERNAL只检测外轮廓;cv2.RETR_LIST检测的轮廓不建立等级关系;cv2.RETR_CCOMP建立两个等级的轮廓,上一层为外边界,内层为内孔的边界。如果内孔内还有连通物体,则这个物体的边界也在顶层;cv2.RETR_TREE建立一个等级树结构的轮廓。
method:轮廓的近似方法。cv2.CHAIN_APPROX_NOME存储所有的轮廓点,相邻的两个点的像素位置差不超过1;cv2.CHAIN_APPROX_SIMPLE压缩水平方向、垂直方向、对角线方向的元素,只保留该方向的终点坐标
contours:是一个Python列表,包含了检测到的所有轮廓。每个轮廓都是一个点集,其中的每个点都是轮廓线上的一个像素位置。
hierarchy:是一个与contours相对应的层级结构,它提供了轮廓之间的层次信息,例如哪些轮廓是相互连接的,
哪些轮廓是嵌套的。绘制图像轮廓函数cv2.drawContours()函数用于在图像上绘制轮廓,可以根据cv2.findContours()函数得到的结果,在原始图像或任何其他图像上绘制轮廓,函数的语法格式如下:
cv2.drawContours(image,contours,contourIdx,color,thickness)
image:二值化图像。
contours:轮廓的点集。
contourIdx:绘制的轮廓索引,-1表示绘制所有轮廓。
color:轮廓颜色。
thickness:轮廓线条宽度。查找并绘制图像轮廓案例importcv2img=cv2.imread("image//shapes.jpg")img1=img.copy()gray=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)#转换为灰度图像_,binary=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)#转换为二值图像#查找图像的外轮廓#cv2.RETR_LIST:绘制所有轮廓,不建立登记关系#cv2.CHAIN_APPROX_SIMPLE:只保留轮廓的必要点,从而压缩轮廓存储contours,_=cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)【例5.10find_contours.py】查找图像轮廓示例。查找并绘制图像轮廓案例#参数意义:#img:在原图像上绘制,contours:轮廓数据,-1:绘制所有轮廓,#(0,255,0)颜色为绿色,1:轮廓线条宽度cv2.drawContours(img1,contours,-1,(0,255,0),1)#显示包含轮廓的图像dWindow("Contours",cv2.WINDOW_KEEPRATIO)#保持显示窗口的长宽比cv2.imshow("img",img)#显示绘制轮廓后的图像cv2.imshow("Contours",img1)#显示绘制轮廓后的图像cv2.waitKey(0)#等待用户按键cv2.destroyAllWindows()#关闭所有窗口查找并绘制图像轮廓案例结果解析:图5.10(a)为原始图像,5.10(b)是调用函数查找图像轮廓并使用绿色线条绘制出的轮廓。
(a)
(b)
例5.10输出结果动动手分别修改本案例中用户查找轮廓和用于绘制轮廓的参数mode、method、contourIdx、color等值比较输出结果有何不同。谢谢!轮廓拟合轮廓拟合
轮廓拟合可用来估计目标轮廓的最小边界或近似形状,包括外接矩形、最小外接圆、椭圆等几何形状,以帮助分析和描述对象的外形特征。这项技术广泛应用于目标检测与跟踪、工业自动化质量控制、医学图像分析、精准农业监测、自动驾驶技术、增强现实、文档处理、体育分析、手写识别以及艺术和设计等领域,提高了系统效率和准确性,同时也为艺术创作和娱乐领域带来了新的可能性。轮廓的外接矩形函数opencv提供函数cv2.boundingRect(contour)函数获取外接矩形,语法格式如下:
Rect=cv2.BoundingRect(Point[]points)
points:一个表示轮廓的点集。通常是通过cv2.FindContours()函数
得到的轮廓,类型为Point[]。这些点通常是轮廓的边界点。
Rect:
表示轮廓的最小外接矩形。该矩形的坐标通常是x,y,表示矩形
左上角的坐标,宽度和高度分别为矩形的宽度和高度。轮廓的外接矩形案例importcv2importnumpyasnp#读取图像并转换为灰度图image=cv2.imread('image//cloud.jpg')gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#转换为灰度图像_,thresh=cv2.threshold(gray,127,255,0)#二值化处理#查找轮廓contours,_=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)【例5.11bounding_rect.py】绘制图像的外接矩形。#contours[1]代表获取第一个轮廓的外接矩形的左上角及宽度、高度值x,y,w,h=cv2.boundingRect(contours[1])cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)cv2.imshow('BoundingRectangle',image)cv2.waitKey(0)cv2.destroyAllWindows()轮廓的外接矩形案例
程序调用cv2.boundingRect(contours[1])获取序号为1的外接矩形的左上角坐标、宽度和高度,然后调用cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)绘制矩形,其中参数(x,y)、(x+w,y+h)分别为外接矩形的左上角和右下角坐标。例5.11输出结果轮廓的最小包围矩形框函数opencv提供了函数cv2.minAreaRect()绘制轮廓的最小包围矩形框,其语法格式为:retval=cv2.minAreaRect(points)
retval:为返回的矩形特征信息,该值的结构为:(最小外接矩形的中心(x,y),(宽度,高度),(旋转角度))。
points:轮廓
注意:返回的retval结构不符合函数cv2.drawContours()参数结构要求,必须将其转换为符合要求的结构才能使用。函数cv2.boxPoints()能够将上述返回值retval转换为符合要求的结构,语法结构如下:points=cv2.boxPoints(box)box:cv2.minAreaRect()返回的值points:能够用于函数cv2.drawContours()参数的轮廓点轮廓的最小包围矩形框案例importcv2importnumpyasnp#读取图像并转换为灰度图image=cv2.imread('image//cloud.jpg')gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#转换为灰度图像_,thresh=cv2.threshold(gray,127,255,0)#二值化处理#查找轮廓contours,_=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#contours[1]代表获取第一个轮廓的外接矩形的左上角及宽度、高度值【例5.12min_rect.py】获取轮廓的最小包围矩形框rect=cv2.minAreaRect(contours[1])print("返回值rect:\n",rect)points=cv2.boxPoints(rect)#将获取的最小包围矩形参数格式进行改变print("\n转换后的points:\n",points)points=points.astype(int)#取整image=cv2.drawContours(image,[points],0,(255,255,0),2)#绘制最包围矩形cv2.imshow("result",image)cv2.waitKey()cv2.destroyAllWindows()轮廓的最小包围矩形框案例
调用cv2.minAreaRect(contours[1])函数返回值rect为三个参数,第一个参数是最小包围矩形左上角坐标,第二个参数是最小包围矩形的宽度和高度,第三个参数是旋转的角度,调用cv2.boxPoints(rect)函数进行格式转换后获得最小包围矩形的四个顶点坐标points,绘制结果如图5.12所示。返回值rect:((184.52781677246094,113.11131286621094),(117.10205841064453,281.7375793457031),81.68487548828125)转换后的points:[[36.67239475.54788][315.4482434.803715][332.38324150.67474][53.60739191.41891]]轮廓的最小外接圆函数opencv提供函数cv2.minEnclosingCircle获取轮廓的最小外接圆,函数的语法格式如下:center,radius=cv2.minEnclosingCircle(points)
points:输入的点集,可以是一个点的列表或数组。
返回值说明:
center:最小外接圆的圆心坐标。
radius:最小外接圆的半径。轮廓的最小外接圆案例importcv2importnumpyasnpimage=cv2.imread('image//cloud.jpg')gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#处理为灰度图像_,thresh=cv2.threshold(gray,127,255,0)#二值化处理contours,_=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)print(len(contours))(x,y),radius=cv2.minEnclosingCircle(contours[1])#调用函数获取最小外接圆参数center=(int(x),int(y))#圆心坐标转换为整数radius=int(radius)#半径转换为整数cv2.circle(image,center,radius,(0,0,255),2)#绘制圆cv2.imshow('MinEnclosingCircle',image)cv2.waitKey(0)cv2.destroyAllWindows()【例5.13min_circle.py】绘制最小外接圆轮廓的最小外接圆案例
程序调用(x,y),radius=cv2.minEnclosingCircle(contours[1])获取索引为1的轮廓的最小外接圆的圆心坐标和半径,然后转换为整形数据,最后用绿色绘制处最小外接圆,如图5.13所示。例5.13输出结果轮廓的最优拟合椭圆函数opencv提供函数cv2.fitEllipse(cnt)获取最优拟合椭圆(x,y),(MA,ma),angle=cv2.fitEllipse(points)
points:输入的点集,可以是一个点的列表或数组。
(x,y):椭圆的中心点。
(MA,ma):椭圆水平方向轴和垂直方向轴的长度。
angle:椭圆的旋转角度。轮廓的最优拟合椭圆案例importcv2importnumpyasnp#读取图像并转换为灰度图image=cv2.imread('image//cloud.jpg')gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)_,thresh=cv2.threshold(gray,127,255,0)#二值化处理#查找轮廓contours,_=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)ellipse=cv2.fitEllipse(contours[1])print(ellipse)cv2.ellipse(image,ellipse,(0,255,0),2)cv2.imshow('BoundingEllipse',image)cv2.waitKey(0)cv2.destroyAllWindows()【例5.14fit_Ellipse.py】绘制轮廓的最优拟合椭圆。轮廓的最优拟合椭圆案例
输出的ellipse值包含了椭圆的中心坐标,椭圆的横轴、纵轴长度、椭圆的旋转角度,绘制结果如图5.14所示。例5.14输出结果((217.88282775878906,215.99325561523438),(116.99994659423828,296.1784362792969),82.30912017822266)谢谢!轮廓的特征值轮廓的特征值的概念
轮廓特征值是图像处理中用于描述和分析图像轮廓属性的关键参数,包括面积、周长、质心、最小外接圆、外接矩形等,它们不仅能够揭示图像中对象的形状和大小,还能提供关于对象位置和方向的重要信息,这些特征值在目标检测、形状分析、特征匹配以及模式识别等多种应用中发挥着核心作用,是连接图像数据与实际应用的桥梁。轮廓的面积函数opecv提供函数cv2.contourArea()计算轮廓面积,函数语法格式如下:area=cv2.contourArea(contour,oriented=False)
contour:输入的轮廓点集,通常是一个NumPy数组。
oriented:布尔值,表示是否考虑轮廓的方向。默认值为
False,表示
返回不带方向的绝对值。如果设置为
True,则返回的面积值会根据轮
廓的方向(顺时针或逆时针)带有正负号。
area:返回的面积值。轮廓的面积的案例importcv2importnumpyasnpimg=cv2.imread('image//shapes.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)edges=cv2.Canny(gray,50,150,apertureSize=3)#使用Canny算法检测边缘#查找轮廓contours,hierarchy=cv2.findContours(edges,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)canvas=np.zeros_like(img)#创建黑色画布【例5.15contourArea.py】计算图中各轮廓大小,将面积大于10000的轮廓用绿色绘制在黑色画布上。轮廓的面积的案例#遍历所有轮廓forcontourincontours:area=cv2.contourArea(contour)#计算轮廓的面积ifarea>10000:#面积大于10000,绘制该轮廓并输出面积print(f'轮廓面积:{area}')cv2.drawContours(canvas,[contour],-1,(0,255,0),2)cv2.imshow('Orig_Image',img)cv2.imshow('Edges',edges)cv2.imshow('Area>10000',canvas)cv2.waitKey(0)cv2.destroyAllWindows()
图5.15(a)是原始图像,5.15(b)是使用Canny边缘检测出的轮廓,可以看出检测出了内轮廓和外轮廓,图5.15(c)是计算轮廓面积后将面积大于10000的轮廓输出的结果。图5.15例5.15输出结果(a)
(b)
(c)轮廓的面积的案例轮廓的周长函数opencv提供函数cv2.arcLength()计算轮廓面积,函数语法格式如下:
perimeter=cv2.arcLength(curve,closed)
curve:输入的轮廓点集,通常是一个NumPy数组。
closed:布尔值,表示轮廓是否闭合。如果轮廓是闭合的,设置为
True;否则,设置为False。
perimeter:返回的周长值。轮廓的周长案例importcv2importnumpyasnpimg=cv2.imread('image//shapes.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度图像edges=cv2.Canny(gray,50,150,apertureSize=3)#Canny算法进行边缘检测#查找轮廓contours,hierarchy=cv2.findContours(edges,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)canvas=np.zeros_like(img)#创建画布forcontourincontours:#遍历所有轮廓【例5.16arcLength.py】计算图像中各轮廓的周长,将周长大于1500的轮廓用红色绘制并输出。轮廓的周长案例perimeter=cv2.arcLength(contour,True)#计算轮廓的周长#如果周长小于1000,则绘制该轮廓并输出周长ifperimeter>500:print(f'轮廓周长:{perimeter}')cv2.drawContours(canvas,[contour],-1,(255,0,255),2)cv2.imshow('Orig_Image',img)cv2.imshow('Perimeter<1500',canvas)cv2.waitKey(0)cv2.destroyAllWindows()轮廓的周长案例图5.16(a)是原图,原图中有多个轮廓,通过for循环分别计算每个轮廓的周长,然后将周长大于1500的轮廓输出,如图5.16(b)所示。5.16输出结果(a)
(b)
轮廓的逼近多边形函数OpenCV提供函数cv2.approxPolyDP()用于对轮廓进行多边形逼近。它采用
Douglas-Peucker算法,将原始轮廓逼近为一个具有指定精度的多边形,从而减少轮廓的点数,简化后的轮廓更容易处理和分析。
reval=cv2.approxPolyDP(curve,epsilon,closed)
curve:输入的轮廓点集。
epsilon:逼近精度,表示原始轮廓与逼近多边形之间的最大距离。epsilon的值越小,逼近的多边形越接近原轮廓。
closed:布尔值,表示轮廓是否闭合。
reval:返回一个近似的多边形轮廓点集。轮廓的逼近多边形案例importcv2importnumpyasnpimg=cv2.imread('image//cloud.png')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)edges=cv2.Canny(gray,50,150,apertureSize=3)contours,hierarchy=cv2.findContours(edges,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)print(len(contours))perimeter=cv2.arcLength(contours[1],True)epsilon=0.01*perimeter#设置逼近精度approx=cv2.approxPolyDP(contours[1],epsilon,True)#逼近多边形点集cv2.drawContours(img,[approx],0,(0,0,255),2)#绘制逼近多边形cv2.imshow('img',img)cv2.waitKey(0)cv2.destroyAllWindows()【例5.17approxPolyDP.py】3.3轮廓的特征值
程序中将逼近多边形的精度设置为epsilon=0.01*perimeter,即为周长的0.01倍,然后用红色线条绘制逼近多边形,结果如图5.17所示。例5.17输出结果动动手试将逼近多边形精度设置为0.03*perimeter,0.005*perimeter,分别比较输出结果,看哪个更接近轮廓?谢谢!凸包及凸缺陷凸包概述
凸包作为图像处理中的一项重要技术,其实际应用广泛,例如在机器视觉中用于物体识别和定位,通过简化目标轮廓提高识别效率;在计算机图形学中,用于创建更加平滑和规则的多边形模型,以优化渲染效果;在地理信息系统(GIS)中,用于从地理数据中提取和分析地形特征;此外,凸包算法也应用于安全监控领域,用于异常行为检测,通过分析人群的凸包变化来识别潜在的安全威胁。这些应用展示了凸包在处理不规则形状目标时的实用性和有效性,使其成为图像分析和模式识别领域中不可或缺的工具。
凸包是给定点集的最小凸多边形包围的区域。在图像处理中,凸包常用于去除图像中的凹陷区域,使目标轮廓更加紧密。在目标检测中,凸包可以将物体边界近似为规则的多边形,适合处理不规则形状的目标。凸包概述
在OpenCV中,凸包是指完全包含原有轮廓,并且仅由轮廓上的点所构成的多边形。凸包的每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部,并且任意连续三个点的内角小于180°。凸包的主要性质如下:
凸性:凸包的每一处都是凸的,即在凸包内连接任意两点的直线都在凸包的内部。
最小性:凸包是包含所有轮廓点的最小凸多边形。
边的相切性:凸包的边与轮廓的边相切。
内角限制:凸包的任意连续三个点的内角小于180°。
绘制凸包的函数OpenCV提供了函数cv2.convexHull来获取凸包,语法如下:cv2.convexHull(points[,hull[,clockwise[,returnPoints]]])
points:输入点集,可以是轮廓或其他点集合。
hull:输出的凸包点集。
clockwise:指定是否按顺时针方向生成凸包。
returnPoints:如果为True返回凸包点集,否则返回点集的索引。绘制凸包的案例importcv2importnumpyasnpimage=cv2.imread('image//hand.bmp')gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)#灰度化ret,binary=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)#二值化contours,hierarchy=cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#假设我们只关心最大的轮廓c=max(contours,key=cv2.contourArea)#获取最大的轮廓hull=cv2.convexHull(c,returnPoints=True)#获取凸包cv2.polylines(image,[hull],True,(0,255,0),2)#绘制凸包cv2.imshow("Image",image)cv2.waitKey(0)cv2.destroyAllWindows()【例5.18hull_hand.py】绘制机械手的凸包。绘制凸包的案例
由图5.18中绿色线条绘制的即是凸包,凸包完全包围机械手轮廓,凸包的任意连续三个点的内角小于180°,凸包包含所有轮廓点的最小凸多边形,符合凸包的性质。例5.18输出结果凸缺陷概述
凸包与轮廓之间的部分称为凸缺陷(ConvexityDefects)。凸缺陷在图像处理和计算机视觉中有广泛的应用,特别是在手势识别和目标检测中。在手势识别中,凸缺陷可以用来识别手的形状和手势。通过计算手部轮廓的凸缺陷,可以确定手指的数量。例如:有4个凸缺陷时,手势表示数值5;有3个凸缺陷时,手势表示数值4;有2个凸缺陷时,手势表示数值3;有1个凸缺陷时,手势表示数值2;有0个凸缺陷时,手势可能表示数值1,也可能表示数值0。在目标检测中,凸缺陷可以用来识别和分析目标的形状特征。通过计算目标轮廓的凸缺陷,可以确定目标的凹陷部分,从而更好地理解目标的形状和结构。这在机器人视觉、工业自动化和安全监控等领域非常有用。
绘制凸缺陷的函数OpenCV提供了函数cv2.convexityDefects()获取凸缺陷。其语法格式如下:convexityDefects=cv2.convexityDefects(contour,convexhull)
contour:轮廓点集。
convexhull:凸包,通常是由cv2.convexHull()返回的索引数组,且returnPoints必须为False。convexityDefects:函数返回一个数组,其中每行包含四个值:起点索引、终点索引、最远点索引和到最远点的近似距离。绘制凸缺陷的案例importcv2importnumpyasnpimage=cv2.imread('image//hand.bmp')gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)ret,binary=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)contours,hierarchy=cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#假设我们只关心最大的轮廓c=max(contours,key=cv2.contourArea)#获取最大轮廓hull=cv2.convexHull(c,returnPoints=False)#获取凸包索引#获取凸缺陷defects=cv2.convexityDefects(c,hull)【例5.19convexity_hand.py】绘制机械手的凸缺陷。绘制凸缺陷的案例#绘制凸缺陷ifdefectsisnotNone:foriinrange(defects.shape[0]):s,e,f,d=defects[i,0]#s起点、e终点、f最远点、d是最远点的距离start=tuple(c[s][0])end=tuple(c[e][0])far=tuple(c[f][0])cv2.line(image,start,end,[0,255,0],2)#绘制凸包cv2.circle(image,far,5,[0,0,255],-1)#实心小圆点标记凸缺陷的点cv2.imshow("Image",image)cv2.waitKey(0)cv2.destroyAllWindows()绘制凸缺陷的案例图5.19中绿色线条绘制的是凸包,红色实心圆标记的是凸缺陷。例5.19输出结果谢谢!任务实施任务实施
利用Python语言和OpenCV库,编写一个程序,实现对图片中手势的识别。程序需要能够读取一张包含手势的图片,通过图像处理技术识别出手势是石头、剪刀还是布,并在
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年抑郁障碍防治宣传课件
- 石英晶体滤波器制造工安全宣贯评优考核试卷含答案
- 客车司机安全操作水平考核试卷含答案
- 2026年护理缺陷分析与改进课件
- 腌腊发酵制品加工工岗中学习考核试卷含答案
- 快件揽收员岗前知识理论考核试卷含答案
- 海水淡化工岗中核心实操考核试卷含答案
- 柠檬酸微生物菌种工岗前基础理论考核试卷含答案
- 风机操作工岗前全能考核试卷含答案
- 上海排水管道安装施工方案
- 矿山井巷施工施工组织设计方案
- 大学生创新创业基础(创新创业课程)完整全套教学课件
- 健康教育学全套课件完整版
- 虚拟电厂整体解决方案
- 批判性思维智慧树知到期末考试答案章节答案2024年浙江大学
- 《工程建设标准强制性条文电力工程部分2023版》
- 大脑动脉狭窄脑梗死的护理查房
- 《噪声敏感建筑物集中区域划分技术规范》编制说明
- 眼科科护士视力检查的实用技术和操作技巧
- 安徽省综合评标评审专家入库、续聘考试试题
- 【新能源汽车充电桩控制系统设计11000字(论文)】
评论
0/150
提交评论