@@ -344,6 +344,37 @@ cv2.waitKey(1000)
344344# 关闭所有窗口
345345cv2.destroyAllWindows()
346346```
347+ ### 绘制箭头
348+
349+ 函数签名:` cv2.arrowedLine(img, start_point, end_point, color, thickness, tipLength) -> img `
350+
351+ 参数说明:
352+
353+ - ` img ` :图像对象
354+ - ` start_point ` :起点坐标
355+ - ` end_point ` :终点坐标
356+ - ` color ` :颜色
357+ - ` thickness ` :线宽
358+ - ` tipLength ` :箭头占比
359+
360+ ``` python showLineNumbers
361+ import cv2
362+ img = cv2.imread(" top.png" )
363+
364+ # 假设 Agent 决定点击 (800, 450)
365+ start_point = (0 , 0 ) # 从下往上画一支箭,更像人伸手
366+ end_point = (100 , 250 ) # 指向目标按钮
367+
368+ img_with_arrow = cv2.arrowedLine(
369+ img, start_point, end_point,
370+ color = (0 , 255 , 255 ), # 黄箭头
371+ thickness = 8 , # 粗箭头,摄像头里都看得清
372+ tipLength = 0.3 # 箭头占比,越大越明显
373+ )
374+
375+ cv2.imwrite(" agent_intent.jpg" , img_with_arrow)
376+ ```
377+
347378
348379### PIL库绘制中文
349380
@@ -444,6 +475,74 @@ cv2.waitKey(0)
444475```
445476:::
446477
478+ ### 图像横向与纵向拼接
479+
480+ 图像拼接的前提是两张图片在拼接方向上的尺寸相同(横向拼接要求高度相同,纵向拼接要求宽度相同)。
481+
482+ 横向拼接函数签名:` cv2.hconcat(src, dst) -> dst ` 或 ` np.hstack((img1, img2, ...)) -> dst `
483+
484+ 纵向拼接函数签名:` cv2.vconcat(src, dst) -> dst ` 或 ` np.vstack((img1, img2, ...)) -> dst `
485+
486+ 参数说明:
487+
488+ - ` src ` :图像列表或元组
489+ - ` dst ` :输出图像
490+
491+ ``` python showLineNumbers
492+ import cv2
493+ import numpy as np
494+
495+ # 读取两张图片
496+ img1 = cv2.imread(" img1.jpg" )
497+ img2 = cv2.imread(" img2.jpg" )
498+
499+ # 确保两张图片高度相同(横向拼接)
500+ h1, w1 = img1.shape[:2 ]
501+ h2, w2 = img2.shape[:2 ]
502+ if h1 != h2:
503+ # 将高度较小的图片调整到与高度较大的图片相同
504+ if h1 < h2:
505+ img1 = cv2.resize(img1, (w1, h2))
506+ else :
507+ img2 = cv2.resize(img2, (w2, h1))
508+
509+ # 方法1:使用 cv2.hconcat 横向拼接
510+ img_horizontal = cv2.hconcat([img1, img2])
511+
512+ # 方法2:使用 np.hstack 横向拼接(效果相同)
513+ # img_horizontal = np.hstack((img1, img2))
514+
515+ # 确保两张图片宽度相同(纵向拼接)
516+ h1, w1 = img1.shape[:2 ]
517+ h2, w2 = img2.shape[:2 ]
518+ if w1 != w2:
519+ # 将宽度较小的图片调整到与宽度较大的图片相同
520+ if w1 < w2:
521+ img1 = cv2.resize(img1, (w2, h1))
522+ else :
523+ img2 = cv2.resize(img2, (w1, h2))
524+
525+ # 方法1:使用 cv2.vconcat 纵向拼接
526+ img_vertical = cv2.vconcat([img1, img2])
527+
528+ # 方法2:使用 np.vstack 纵向拼接(效果相同)
529+ # img_vertical = np.vstack((img1, img2))
530+
531+ # 显示结果
532+ cv2.imshow(" Horizontal" , img_horizontal)
533+ cv2.imshow(" Vertical" , img_vertical)
534+ cv2.waitKey(0 )
535+ cv2.destroyAllWindows()
536+
537+ # 保存结果
538+ cv2.imwrite(" horizontal.jpg" , img_horizontal)
539+ cv2.imwrite(" vertical.jpg" , img_vertical)
540+ ```
541+
542+ :::tip
543+ 如果图片尺寸不一致,需要先使用 ` cv2.resize() ` 调整尺寸,确保在拼接方向上尺寸相同。
544+ :::
545+
447546## 基础图像操作
448547
449548### 图像缩放
@@ -813,8 +912,8 @@ HSV:相比RGB相比,HSV能更好的表示同个颜色的不同值(饱和
813912
814913### 灰度图
815914
816- 灰度图
817- 适用于图像处理,如边缘检测及其应用:图像分割、轮廓检测
915+ 灰度图适用于图像处理,如边缘检测及其应用:图像分割、轮廓检测
916+
818917只有1个通道,取值范围是0-255,表示颜色的亮度
819918
820919``` python showLineNumbers
@@ -842,10 +941,7 @@ cv2.destroyAllWindows()
842941
843942### 二值化图
844943
845- 二值化图
846- 适用于图像压缩
847- 只有1个通道,取值范围是0或1
848-
944+ 二值化图,适用于图像压缩。只有1个通道,取值范围是0或1
849945
850946| 方法 | 核心思想 | 如何工作? | 优点 | 缺点 | 适用场景 |
851947| :--- | :--- | :--- | :--- | :--- | :--- |
@@ -873,6 +969,28 @@ cv2.destroyAllWindows()
873969归一化的目的是消除数据量纲和尺度的影响,使得不同尺度或单位的数据可以在同一水平上进行比较或处理。
874970:::
875971
972+ 函数签名:` cv2.threshold(img, thresh, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) -> retval, dst `
973+
974+ 参数说明:
975+
976+ - ` img ` :输入灰度图像
977+ - ` thresh ` :阈值(Otsu方法中通常设为0,会自动计算最佳阈值)
978+ - ` 255 ` :当像素值超过阈值时赋予的新值(maxValue)
979+ - ` cv2.THRESH_BINARY + cv2.THRESH_OTSU ` :二值化类型,OTSU会自动计算最佳阈值
980+
981+ 主要用于缺陷检测
982+
983+ 函数签名:` cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) -> dst `
984+
985+ 参数说明:
986+
987+ - ` img ` :输入灰度图像
988+ - ` 255 ` :当像素值超过阈值时赋予的新值(maxValue)
989+ - ` cv2.ADAPTIVE_THRESH_GAUSSIAN_C ` :自适应方法,使用高斯加权
990+ - ` 11 ` :用于计算阈值的邻域大小(blockSize,必须为奇数)
991+ - ` 2 ` :从平均值或加权和中减去的常数(C)
992+
993+ 主要用于光照不均匀的场景
876994
877995``` python showLineNumbers
878996import cv2
@@ -935,11 +1053,11 @@ def get_binary_image(img, method, *args, **kwargs):
9351053 # 全局平均值法
9361054 _, binary = cv2.threshold(img, img.mean(), 255 , cv2.THRESH_BINARY )
9371055 elif method == ' adaptive_mean' :
938- # 自适应均值阈值法
1056+ # 自适应均值阈值法(光照不均匀时效果更好)
9391057 binary = cv2.adaptiveThreshold(img, 255 , cv2.ADAPTIVE_THRESH_MEAN_C ,
9401058 cv2.THRESH_BINARY , 11 , 2 )
9411059 elif method == ' adaptive_gaussian' :
942- # 自适应高斯阈值法
1060+ # 自适应高斯阈值法(光照不均匀时效果更好)
9431061 binary = cv2.adaptiveThreshold(img, 255 , cv2.ADAPTIVE_THRESH_GAUSSIAN_C ,
9441062 cv2.THRESH_BINARY , 11 , 2 )
9451063 elif method == ' otsu' :
@@ -1028,6 +1146,41 @@ cv2.destroyAllWindows()
10281146- 黑帽: 闭运算 - 原图,用于填充图像中的小孔洞
10291147:::
10301148
1149+ ### 开运算和闭运算
1150+
1151+ 开运算和闭运算主要用于去除图像中的小噪声和小孔洞、粘连断裂。
1152+
1153+ 开运算函数签名:` cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) -> dst `
1154+
1155+ 闭运算函数签名:` cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) -> dst `
1156+
1157+ 参数说明:
1158+
1159+ - ` img ` :输入图像
1160+ - ` cv2.MORPH_OPEN ` :开运算操作类型(先腐蚀后膨胀)
1161+ - ` cv2.MORPH_CLOSE ` :闭运算操作类型(先膨胀后腐蚀)
1162+ - ` kernel ` :形态学操作的核
1163+
1164+ ``` python showLineNumbers
1165+ import cv2
1166+ import numpy as np
1167+
1168+ img = cv2.imread(" dt2.png" )
1169+ kernel = np.ones((3 , 3 ), np.uint8)
1170+
1171+ # 开运算:先腐蚀后膨胀,用于去除图像中的小噪声
1172+ opening = cv2.morphologyEx(img, cv2.MORPH_OPEN , kernel)
1173+
1174+ # 闭运算:先膨胀后腐蚀,用于填充图像中的小孔洞
1175+ closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE , kernel)
1176+
1177+ cv2.imshow(" Original" , img)
1178+ cv2.imshow(" Opening" , opening)
1179+ cv2.imshow(" Closing" , closing)
1180+ cv2.waitKey(0 )
1181+ cv2.destroyAllWindows()
1182+ ```
1183+
10311184
10321185### 模糊
10331186
@@ -1159,7 +1312,7 @@ cv2.destroyAllWindows()
11591312
11601313## 算法指路
11611314
1162- 下面是Opencv常用的算法,每个算法都比较复杂且可能随时间变化出现新的算法,因此随用随学即可。
1315+ 下面是Opencv常用的算法,每个算法都比较复杂且可能随时间变化出现新的算法,因此随用随学即可。另外,大部分算法也有深度学习的版本,效果更好。
11631316
11641317想获得认证可以参与[ OpenCV Bootcamp] ( https://courses.opencv.org/courses/course-v1:OpenCV+Bootcamp+CV0/course/ )
11651318
@@ -1649,9 +1802,7 @@ video_out.release()
16491802
16501803```
16511804
1652- ### 人体相关
1653-
1654- #### 人脸检测
1805+ ### 人脸检测
16551806
16561807人脸检测算法广泛应用于身份验证、考勤系统、社交媒体标记、美颜相机和安防监控中。
16571808
@@ -1784,17 +1935,6 @@ if __name__ == "__main__":
17841935 recognizer()
17851936```
17861937
1787- #### 其他
1788-
1789- 人体检测算法广泛应用于智能安防、客流统计、健身应用、体感游戏和自动驾驶系统中。
1790-
1791- 人体姿态估计主要用于健身指导、医疗康复、运动分析、动作捕捉和人机交互界面。
1792-
1793- 手势识别技术应用于智能家居控制、手语翻译、VR/AR交互、游戏控制和辅助残障人士交流。
1794-
1795- 动作识别算法用于视频内容理解、体育比赛分析、异常行为检测、健身应用和人机交互。
1796-
1797- 行为识别技术主要应用于安防监控、智慧城市、客户行为分析、老人看护和异常事件预警。
17981938
17991939## YOLO
18001940
@@ -1811,7 +1951,7 @@ if __name__ == "__main__":
18111951
18121952经过测试:opencv加载YOLOv11模型,与原生yolo的FPS一致、内存占用一致。Opencv的CPU占用率更高。
18131953
1814- 所以使用OpenCV的唯一原因是可以用 ` C++ ` 版本的代码,在无python依赖的设备上运行,适合资源受限的边缘设备 。
1954+ 所以使用OpenCV的唯一原因是打包为可执行文件后体积更小 。
18151955:::
18161956
18171957### 导出模型
0 commit comments