当前位置: 首页 > news >正文

浏览器正能量网站免费图片墙外行人 wordpress

浏览器正能量网站免费图片,墙外行人 wordpress,网站建设中如何发布信息推广,注册域名需要多久Open Source Computer Vision Library。OpenCV是一个#xff08;开源#xff09;发行的跨平台计算机视觉库#xff0c;可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C 类构成#xff0c;同时提供了Python、Ruby、MATLAB等语言的…Open Source Computer Vision Library。OpenCV是一个开源发行的跨平台计算机视觉库可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C 类构成同时提供了Python、Ruby、MATLAB等语言的接口实现了图像处理和计算机视觉方面的很多通用算法。在学习过程中遇到问题最好的办法就是查询opencv官方文档。 笔者的运行环境python3.7pycharmopencv4.6资源下载点这里哦 1. 图像的读取、显示与写入 图像的读取、显示与写入分别对应三个函数cv2. imread()、cv2.imshow()、cv2.imwrite()。 1.1. 读取图像 语法cv2.imread(filename[, flags])---image参数filename---文件路径相对路径和绝对路径路径中不要带有中文。flags---可选标志用于指定读取图像的样式常见的有cv2.IMREAD_UNCHANGED(-1)、cv2.IMREAD_GRAYSCALE(0)、cv2.IMREAD_COLOR(1)。默认为1。注意opencv读取彩色图像的格式是BGR而大多数视觉库使用的是RGB因此当将 OpenCV 与其他工具包一起使用时当从一个库切换到另一个库时不要忘记交换蓝色和红色通道。 1.2. 显示图像 语法cv2.imshow(window_name, image)---None参数window_name---显示图像的窗口的名字。image---显示图像的变量名。注意该函数一般和cv2.waitKey()、cv2.destroyAllWindows()、cv2.destroyWindow()一起使用。cv2.waitKey()函数是键盘绑定函数等待键击任意键或指定键继续程序。cv2.destroyAllWindows()用于销毁全部窗口从内存中清除、cv2.destroyWindow()销毁指定窗口从内存中清除。 import cv2 # 查看opencv版本print(cv2.getVersionString()) # 读取图像image_unchanged  cv2.imread(image\\cat.jpg, cv2.IMREAD_UNCHANGED)image_grayscale  cv2.imread(image\\cat.jpg, cv2.IMREAD_GRAYSCALE)image_color  cv2.imread(image\\cat.jpg, cv2.IMREAD_COLOR) # 显示图像cv2.imshow(unchanged, image_unchanged)cv2.imshow(grayscale, image_grayscale)cv2.imshow(color, image_color) # 永远暂停程序直到键击任意键cv2.waitKey(0)# 销毁所有窗口cv2.destroyAllWindows() 运行结果 1.3. 写入图像 语法cv2.imwrite(filename, image[, params])参数filename---文件名它必须包含文件的扩展名如.jpg、.pngimage----要保存的图像变量名。 import cv2 image_grayscale  cv2.imread(image\\cat.jpg, cv2.IMREAD_GRAYSCALE)cv2.imshow(grayscale, image_grayscale)cv2.imwrite(image\\cat_grayscale.jpg, image_grayscale)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 2. 图像的色彩空间 常用的图像色彩空间有RGB、Lab、YCrCb、HSV等模式RGB模式通过对红R、绿G、蓝B三个颜色通道的变化以及它们相互之间的叠加来得到各种颜色。依赖于光线。R、G、B的取值范围[0, 255]。容易理解但连续变换时不直观。详见RGB_百度百科Lab模式它是一种设备无关的颜色模型也是一种基于生理特征的颜色模型。它由亮度L、颜色a绿色到洋红色b蓝色到黄色组成。详见Lab颜色模型_百度百科YCrCb模式它派生自RGB颜色模式主要应用在优化彩色视频信号的传输使其向后相容老式黑白电视。Y伽马校正后从RGB获得的亮度或亮度分量Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。HSV模式它是H、S、V三维颜色空间中的一个可见光子集。是为了数字化图像提出来的不能很好的表示人眼解释图像的过程。H色相S饱和度V明度。取值范围H---[0, 179]S---[0, 255]V---[0, 255]。详见HSV颜色模型_百度百科灰度图图像是有不同灰度的像素组成的每个像素都是在[0, 255]取值。根据人眼敏感度把RGB图片转换为灰度图不是简单把RGB每个通道取平均值而是Y 0.299R 0.587G 0.114*B注意必须要指出的是图像就是一个数组因此可以使用image.shape查询形状其输出结果为 (pixel_height, pixel_width, 3)。pixel_height、pixel_width代表图像的像素尺寸3代表每个像素的颜色是由一个三维数组确定的opencv中是BGR模式的数组。如何查看某像素的RGB、Lab、YCrCb、HSV值由于在读取图像时直接读取的是RGB值因此可通过cv2.imshow()函数直接查看。利用cv2.cvtColor(np.uint8([[[image[x, y]]]]), cv2.COLOR_BGR2Lab)[0][0]查看位置x, y处的Lab值。YCrCb、HSV与Lab类似。注意图像中某位置的图像色彩空间转换为其他时必须要使其BGR 空间值由三个通道组成三维化。练习如何通过鼠标的移动实时获取指定图片的不同色彩空间值 import cv2import globimport numpy as np # 定义鼠标回调的‘动作’函数def showPixelValue(event, x, y, flags, param): # 定义全局变量 global img, combinedResult, placeholder # 判断鼠标是否移动 if event  cv2.EVENT_MOUSEMOVE: # 获取鼠标坐标的RGB值 bgr  img[y, x] # 转换色彩空间值 ycb  cv2.cvtColor(np.uint8([[bgr]]), cv2.COLOR_BGR2YCrCb)[0][0] lab  cv2.cvtColor(np.uint8([[bgr]]), cv2.COLOR_BGR2Lab)[0][0] hsv  cv2.cvtColor(np.uint8([[bgr]]), cv2.COLOR_BGR2HSV)[0][0] # 创建一个与载入图片高度相同的黑色图块作为结果区域 placeholder  np.zeros((img.shape[0], 400, 3), dtypenp.uint8) # 在结果区域内显示鼠标位置不同色彩空间的值 cv2.putText(placeholder, BGR {}.format(bgr), (20, 70), cv2.FONT_HERSHEY_COMPLEX, .9, (255, 255, 255), 1, cv2.LINE_AA) cv2.putText(placeholder, HSV {}.format(hsv), (20, 140), cv2.FONT_HERSHEY_COMPLEX, .9, (255, 255, 255), 1, cv2.LINE_AA) cv2.putText(placeholder, YCrCb {}.format(ycb), (20, 210), cv2.FONT_HERSHEY_COMPLEX, .9, (255, 255, 255), 1, cv2.LINE_AA) cv2.putText(placeholder, LAB {}.format(lab), (20, 280), cv2.FONT_HERSHEY_COMPLEX, .9, (255, 255, 255), 1, cv2.LINE_AA) # 合并加载的图片和结果区域 combinedResult  np.hstack([img, placeholder]) # 显示合并后的图像 cv2.imshow(PRESS P for Previous, N for Next Image, combinedResult) if __name__  __main__: # 读取指定的图片并转换尺寸 files  glob.glob(image/rub*.jpg) files.sort() img  cv2.imread(files[0]) img  cv2.resize(img, (400, 400)) # 显示转换尺寸后的图像在‘PRESS...’显示框加载 cv2.imshow(PRESS P for Previous, N for Next Image, img) # 创建一个无加载图像的显示框并覆盖了原‘PRESS...’显示框 cv2.namedWindow(PRESS P for Previous, N for Next Image) # 创建一个鼠标回调加载回调‘动作’函数并且该动作在‘PRESS...’显示框内实现 cv2.setMouseCallback(PRESS P for Previous, N for Next Image, showPixelValue) i  0 while 1: k  cv2.waitKey(1)  0xFF # 键击‘n’切换到下一张图片 if k  ord(n): i  1 img  cv2.imread(files[i % len(files)]) img  cv2.resize(img, (400, 400)) cv2.imshow(PRESS P for Previous, N for Next Image, img) # 键击‘p’切换到上一张图片 elif k  ord(p): i - 1 img  cv2.imread(files[i % len(files)]) img  cv2.resize(img, (400, 400)) cv2.imshow(PRESS P for Previous, N for Next Image, img) # 键击‘Esc’退出程序 elif k  27: cv2.destroyAllWindows() break 运行结果如下静态展示 image.png 3. 图像编辑 图像编辑主要包括调整图像大小、裁剪图像、图像的旋转和移动、翻转透视变换。 3.1. 调整大小 在opencv中使用image.shape获得图像大小image.shape获得结果是(heigh, width, channels)即高度、宽度、通道数。在opencv中使用resize()函数调整图像的大小。语法cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])---dst参数src---源图像。dsize---可为tuple参数或None。目标图像的大小即新的图像宽高。需要注意的是dsize(width, height)中第 一个参数是图像宽度第二个是高度与shape(height, width, channels)的相对位置刚好相反。dst---目标图像在python中无任何意义一般不传参或设成None。fx---沿水平轴的比例因子。fy---沿垂直轴的比例因子。interpolation---插值方式提供了调整图像大小的不同方法。其本质是一个int数值不过一般用opencv内置的参 数名称以提高可读性。默认为cv2.INTER_LINEAR。其他还有cv2.INTER_AREA、cv2.INTER_CUBIC、cv2.INTER_NEAREST。注意当目标图像与源图像的宽高比不一致代表经缩放后图像失真。关于插值参数①要缩小图片选用cv2.INTER_AREA②放大图片选用cv2.INTER_CUBIC速度慢或cv2.INTER_LINEAR速度快效果还行。 import cv2 cat  cv2.imread(image\\cat.jpg) # 指定目标图像的宽高# 图像不失真cat_down_0  cv2.resize(cat, (150, 150))cat_up_0  cv2.resize(cat, (500, 500))cv2.imshow(cat_down-No distortion, cat_down_0)cv2.imshow(cat_up-No distortion, cat_up_0)# 图像失真cat_distortion  cv2.resize(cat, (200, 300))cv2.imshow(cat distortion, cat_distortion)cv2.waitKey(0)cv2.destroyAllWindows() # 指定图像的比例因子(需要指出的是dsize必须要传参None)# 图像不失真cat_down_1  cv2.resize(cat, None, fx0.75, fy0.75)cat_up_1  cv2.resize(cat, None, fx1.2, fy1.2)cv2.imshow(cat_down-No distortion1, cat_down_1)cv2.imshow(cat_up-No distortion1, cat_up_1)# 图像失真cat_distortion1  cv2.resize(cat, None, fx0.75, fy1.2)cv2.imshow(cat distortion1, cat_distortion1)cv2.waitKey(0)cv2.destroyAllWindows() # 指定图像缩放方法cat_scale0  cv2.resize(cat, (150, 150), interpolationcv2.INTER_AREA)cat_scale1  cv2.resize(cat, (450, 450), interpolationcv2.INTER_CUBIC)cat_scale2  cv2.resize(cat, (450, 450), interpolationcv2.INTER_LINEAR)cat_scale3  cv2.resize(cat, (150, 150), interpolationcv2.INTER_NEAREST)cv2.imshow(cat_scale0, cat_scale0)cv2.imshow(cat_scale1, cat_scale1)cv2.imshow(cat_scale2, cat_scale2)cv2.imshow(cat_scale3, cat_scale3)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果部分如下 3.2. 图像裁剪 裁剪图像是为了从图像中删除不需要的对象或区域也就是删除其他保留想要的图像区域。opencv中的图像裁剪是利用numpy数组切片的方法来实现的。首先我们要知道图像就是一个数组其由高、宽、通道数三个维度组成。仅对图像进行裁剪就是意味着对宽和高两个维度进行切片操作。具体如下语法image[start_row : end_row, start_col : end_col]---dst参数start_row 、end_row---图像的开始与结束的行坐标。start_col :、end_col---图像的开始与结束的列坐标。注意图像可视为坐标系坐标原点为图像的左上角顶点裁剪区域即是四条直线的围合区域。 import cv2 cat  cv2.imread(image\\cat.jpg)print(cat.shape)# 裁剪图像cropped_cat  cat[25:190, 50:300]cv2.imshow(original, cat)cv2.imshow(cropped, cropped_cat)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 3.3. 旋转和平移 图像的旋转和平移是图像编辑中最基本的操作之一。旋转和平移都属于同一种图像编辑类型即放射变换(Affine transformations)类型。旋转和平移都是借助cv2.warpAffine()函数实现的其区别是转换矩阵M的不同。旋转利用cv2.getRotationMatrix2D()函数构造旋转矩阵平移矩阵利用二维数组构建。 首先看一下仿射变换函数cv.warpAffine()。需要指出的是图像变换时其坐标系是不变的与源图像一致。语法cv2.warpAffine(src, M, desize[, dst[, flags[, borderMode[, borderValue]]]])---dst参数src---源图像。M---转换矩阵。desize---tuple类型参数。目标图像的宽高即新的图像宽高(新的图像可能包含部分或者全部变换后的图像其他区域一般由黑色像素填充)。坐标系遵循源图像坐标系。dst---目标图像在python中无任何意义一般不传参或设成None。flags---插值方法。cv2.INTER_NEAREST最近邻插值cv2.INTER_LINEAR线性插值默认值cv2.INTER_AREA区域插值cv2.INTER_CUBIC三次样条插值cv2.INTER_LANCZOS4Lanczos插值等。borderMode---边界像素模式。borderValue---边界填充值即显示框内图像之外的区域默认值为0。 旋转矩阵的构造cv2.getRotationMatrix2D()。语法cv2.getRotationMatrix2D(center, angle, scale)---M参数center---图像的旋转中心是一个元组类型的参数。即在图像构建的坐标系中选取旋转中心。angle---旋转角度角度制正负值遵循坐标系角度规则。scale---图像的缩放比例因子。 平移矩阵的构造。构造数组2Darray np.ndarray([[1 0 tx], [0, 1, ty]])参数tx---正值图像将右移|tx|个像素负值将向左移|tx|个像素。ty---正值图像将下移|ty|个像素负值将向上移|ty|个像素平移矩阵M 2Darray import cv2import numpy as np cat  cv2.imread(image\\cat.jpg)print(cat.shape)height, width  cat.shape[:2] # 旋转图像center  (width/3, height/10)rotate_matrix  cv2.getRotationMatrix2D(center, -15, scale1.2)rotated_cat  cv2.warpAffine(cat, rotate_matrix, dsize(500, 300))# 原图像以坐标width/3, height/10为旋转中心旋转-15度然后再缩放1.2倍cv2.imshow(original image, cat)cv2.imshow(rotated_cat, rotated_cat)cv2.waitKey(0)cv2.destroyAllWindows() # 平移图像tx, ty  width/5, -height/5translation_matrix  np.array([[1, 0, tx], [0, 1, ty]])translation_cat  cv2.warpAffine(cat, translation_matrix, dsize(500, 300))cv2.imshow(original image, cat)cv2.imshow(translation_cat, translation_cat)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 3.4. 图像翻转 图像翻转也就是通常所说的镜像。主要包括垂直翻转、水平翻转、水平垂直翻转。语法cv2.flip(src, flipCode[, dst])---dst参数src---源图像。flipCode---翻转方式。flipCode 0垂直翻转沿x轴翻转flipCode0水平翻转沿y轴翻转flipCode 0水平垂直翻转先沿X轴翻转再沿Y轴翻转等价于旋转180°。 import cv2import numpy as np cat  cv2.imread(image\\cat.jpg)# 翻转图像flip_cat1  cv2.flip(cat, flipCode0)flip_cat2  cv2.flip(cat, flipCode1)flip_cat3  cv2.flip(cat, flipCode-1)combined  np.hstack((cat, flip_cat1, flip_cat2, flip_cat3))cv2.imshow(combined, combined)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果 4. 图像注释 注释图像即是在图像添加注释性信息通常是绘制图形标出对象或者添加文字信息。需要指出的是在进行注释图像前一定要使用copy()方法创建副本以确保源图像的完整性。 4.1. 绘制直线 语法cv2.line(image, start_point, end_point, color, thickness)---image参数image---图像通常是源图像的副本。start_point---直线的起点坐标元组参数。end_point---直线的终点坐标元组参数。color---直线的颜色元组参数。thickness---直线的厚度。注意start_point与end_point的值第一个值代表的是横轴值第二个值代表的是竖轴值可简单理解为x、y轴的值。 import cv2 girl  cv2.imread(image\\girl.jpg)print(girl.shape)# 绘制一条长260像素的横向白色线girl_line  girl.copy()cv2.line(girl_line, (0, 250), (260, 250), (255, 255, 255), thickness2)cv2.imshow(girl_line, girl_line)cv2.waitKey()cv2.destroyAllWindows() 运行结果如下 4.2. 绘制圆形 语法cv2.circle(image, center_coordinates, radius, color[, thickness[, lineType[, shift]]])---image参数image---图像通常是源图像的副本。center_coordinates---圆形的圆心坐标元组参数。radius---圆形的半径。color---直线的颜色元组参数。thickness---正值直线的厚度负值表示绘制一个填充圆。lineType---圆边线类型。shift---圆心和半径值中的小数位数。注意start_point与end_point的值第一个值代表的是横轴值第二个值代表的是竖轴值可简单理解为x、y轴的值。 import cv2 # 绘制一个圆形girl  cv2.imread(image\\girl.jpg)girl_circle  girl.copy()cv2.circle(girl_circle, (380, 270), 175, (255, 255, 255), thickness2)cv2.imshow(girl_circle, cv2.resize(girl_circle, None, fx0.6, fy0.6)) # 绘制一个填充圆girl_circle1  girl.copy()cv2.circle(girl_circle1, (380, 270), 175, (255, 255, 255), thickness-1)cv2.imshow(girl_circle1, cv2.resize(girl_circle1, None, fx0.6, fy0.6))cv2.waitKey()cv2.destroyAllWindows() 运行结果如下 4.3. 绘制矩形 语法cv2.rectangle(image, start_point, end_point, color[, thickness[, lineType[, shift]]])---image参数image---图像通常是源图像的副本。start_point---矩形的起始点即其左上角元组参数。end_point---矩形的终点即其右下角 元组参数。color---直线的颜色元组参数。thickness---正值直线的厚度负值表示绘制一个填充矩形。lineType---矩形边线类型。shift---坐标中的小数位数。注意start_point与end_point的值第一个值代表的是横轴值第二个值代表的是竖轴值可简单理解为x、y轴的值。 import cv2 # 绘制一个矩形girl  cv2.imread(image\\girl.jpg)print(girl.shape)girl_rec  girl.copy()cv2.rectangle(girl_rec, (200, 170), (570, 400), (255, 255, 255), thickness2)cv2.imshow(girl_rec, cv2.resize(girl_rec, None, fx0.6, fy0.6)) # 绘制一个填充矩形girl_rec1  girl.copy()cv2.rectangle(girl_rec1, (200, 170), (570, 400), (255, 255, 255), thickness-2)cv2.imshow(girl_rec1, cv2.resize(girl_rec1, None, fx0.6, fy0.6))cv2.waitKey()cv2.destroyAllWindows() 运行结果如下 4.4. 绘制椭圆 语法cv2.ellipse(image, center, axesLength, angle, startAngle, endAngle, color[, thickness[,lineType[, shift]]])---image参数image---图像通常是源图像的副本。centert---椭圆的圆心坐标元组参数。axesLength---椭圆长轴与短轴大小的一半元组参数。angle---椭圆的旋转角度角度制。startAngle---椭圆弧的起始角度。endAngle---椭圆弧的结束角度。color---直线的颜色元组参数。thickness---正值直线的厚度负值表示绘制一个填充矩形。lineType---椭圆边线类型。shift---坐标中的小数位数。注意①椭圆的角度均遵循顺逆时针规则x轴正半轴为起始轴顺时针为正逆时针为负。②先绘制正常的椭圆然后再根据参数angle以center为旋转中心旋转椭圆。 import cv2 # 绘制一个椭圆girl  cv2.imread(image\\girl.jpg)print(girl.shape) girl_ellipse  girl.copy()cv2.ellipse(girl_ellipse, (380, 300), (200, 100), 45, 180, 360, (255, 255, 255), thickness2)cv2.ellipse(girl_ellipse, (380, 300), (200, 100), 45, 0, 180, (0, 0, 255), thickness2)cv2.imshow(girl_ellipse, girl_ellipse)cv2.waitKey()cv2.destroyAllWindows() 运行结果如下 4.5. 添加文本 语法cv2.putText(image, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])---image参数image---图像通常是源图像的副本。text---文本字符串。org---text的左下角的位置。fontFace---字体类型。fontScale---字体的比例用于乘以特定字体的基大小。color---字体颜色。thickness---文本字体线条的粗细lineType---字体边线类型。bottomLeftOrigin---如果为 true则图像数据原点位于左下角。否则它位于左上角。 import cv2 girl  cv2.imread(image\\girl.jpg)print(girl.shape)girl_putText  girl.copy()text  Finally, let’s try annotating images with text. To do this, use the function in OpenCVcv2.putText(girl_putText, text, (50, 400), cv2.QT_FONT_BLACK, 0.85, (255, 255, 255))cv2.imshow(1111, girl_putText)cv2.waitKey()cv2.destroyAllWindows() 运行结果如下 5. 鼠标回调函数和跟踪栏回调函数 鼠标回调函数和跟踪栏可以达到如下动图的效果 鼠标指针是图形用户界面GUI中的关键组件没有鼠标指针就无法真正做到图形界面的人机交互。opencv中与鼠标指针相关的有两个重要的函数即鼠标回调函数和创建跟踪栏。 5.1. 鼠标回调函数 我们通过实现鼠标标注图像这一功能来了解鼠标回调函数。首先定义一个特殊的“回调”函数该函数将在显示窗口中显示的图像上绘制一个矩形。仅在计算机检测到某些用户界面事件时调用的函数被称为“回调”函数。由于这个函数与鼠标相关联因此一般命名为MouseCallback不过你也可以自定义。这个函数在调用时无需输入任何参数这是因为在用户与鼠标进行交互时所需参数会自动填充。然后将“回调”函数与特定的鼠标事件相关联。每当调用此函数用户和鼠标交互时位于显示图像上的鼠标会记录鼠标x轴、y轴的坐标并记录鼠标的事件类型和事件标志。对于本例当触发动作 cv2.LEFTBUTTONDOWN 和 cv2.LEFTBUTTONUP 时我们将坐标存储在各自的变量中并使用它们来绘制矩形。 ①怎么定义鼠标回调函数语法def MouseCallback(event, x, y, flags, userdata)参数event---鼠标事件。x, y---鼠标的x轴和y轴的坐标。flags---事件标志。userdata---其他的输入数据。注意定义回调函数时函数名是可变的。 ②怎么调用鼠标回调函数使用cv2.setMouseCallback()函数来调用鼠标回调函数。语法cv2.setMouseCallback(winname, onMouse[, userdata])参数winname---窗口名称必须是已经存在的窗口。onMouse---鼠标回调函数名。userdata传递给回调函数的可选参数。 ③怎么使显示窗口和用户发生交互利用while循环和cv2.waitKey()函数指定键盘字符发生交互。具体而言 创建一个持续显示图像的 while 循环直到用户按 q 键ASCII 代码113退出应用程序脚本。在循环中为用户提供清除所有先前批注的功能。用户可以将命名窗口中的图像重置为我们在原始图像中读取时所做的副本。这可以通过检查键盘条目“c”ASCII 代码99来实现。当用户退出循环时我们使用cv2.destroyAllWindows() 销毁窗口。 ④代码的具体实现。 import cv2 # 初始化参数top_left_corner, bottom_right_corner  [], [] # flags*userdata虽然没有调用但不可缺少def drawRectangle(event, x, y, flags, *userdata): global top_left_corner, bottom_right_corner if event  cv2.EVENT_LBUTTONDOWN: top_left_corner  [(x, y)] elif event  cv2.EVENT_LBUTTONUP: bottom_right_corner  [(x, y)] cv2.rectangle(image, top_left_corner[0], bottom_right_corner[0], (0, 255, 0), 2, 8) cv2.imshow(Window, image) image  cv2.imread(image\\cat.jpg)temp  image.copy()cv2.namedWindow(Window)cv2.setMouseCallback(Window, drawRectangle) k  0# 键击‘q’退出程序键击‘c’重新绘制矩形while k ! 113: cv2.imshow(Window, image) k  cv2.waitKey(0) if k  99: image  temp.copy() cv2.imshow(Window, image) cv2.destroyAllWindows() 运行过程截图 5.2. 跟踪栏回调函数 跟踪栏回调函数与鼠标回调函数类似。 ①怎么定义跟踪栏回调函数语法def TrackbarCallback(args)参数args---跟踪栏参数。args[0]可以检索跟踪栏条目位置这是一个与用户发生交互的参数其范围是0, count]内的整数。注意定义回调函数时函数名是可变的。 ②怎么调用跟踪栏回调函数使用cv2.createTrackbar()函数来调用跟踪栏回调函数。语法cv2.createTrackbar(trackbarName, winname, value, count, onChange[, userdata])参数trackbarName---创建的跟踪栏名称。winname---显示窗口的名称。value---滑块的默认位置。count---滑块可滑到的最大位置。onChange---回调函数名。userdata---传递给回调函数的用户数据。它可用于处理跟踪栏事件而无需使用全局变量。 ③代码的具体实现。 import cv2 # 初始化参数maxScaleUp  100scaleFactor  1windowName  Resize ImagetrackbarValue  Scale # 创建回调函数图像可以在[1, 2]之间缩放def scaleImage(*args): scaleFactor  1  args[0] scaledImage  cv2.resize(image, None, fxscaleFactor, fyscaleFactor, interpolationcv2.INTER_LINEAR) cv2.imshow(windowName, scaledImage) image  cv2.imread(image\\jellyfish.jpg)cv2.namedWindow(windowName, cv2.WINDOW_AUTOSIZE)# 调用跟踪栏回调函数cv2.createTrackbar(trackbarValue, windowName, scaleFactor, maxScaleUp, scaleImage) cv2.imshow(windowName, image)c  cv2.waitKey(0)cv2.destroyAllWindows() 运行过程截图 6. 图像过滤 opencv使用卷积内核模糊平滑、锐化图像也就是过滤图像。本节涉及到了卷积建议对卷积有个基本了解可参考如何通俗易懂地解释卷积 - 知乎 本小节以下内容的图文来自如何通俗易懂地解释卷积 - 马同学的回答。 6.1 卷积核及其应用 卷积核也被称为卷积矩阵是用于过滤图像的二维矩阵它通常是一个N阶方阵其中N是奇数。卷积核的作用使用卷积核对图像的每个像素执行数学运算可以达到模糊平滑或锐化图像的目的。 卷积计算 前面已经提到图像就是一个三维数组当去掉通道维度时它就是一个矩阵可用于参与矩阵的运算。比如下图的噪点较多此时我们可以使用卷积操作将图像进行平滑处理。具体过程如下①用矩阵表示图像 ②设置卷积核卷积矩阵做归一化处理不改变图像的亮度。需要注意的是图像处理中一般用的是正态分布矩阵这里为了简单就用了算术平均矩阵 ③卷积计算。若要平滑a1,1点就在矩阵中取出a1,1 点附近的点组成矩阵 f形状与卷积矩阵相同 和卷积核进行卷积计算后再填回去 下面用一个动图诠释计算过程 ④写成一个公式 将卷积核应用于图像 这里的仅简单介绍cv2.filter()函数。语法cv2.filter2D(src, ddepth, kernel)---dst参数src---源图像。ddepth---目标图像的深度值。-1表示目标图像与源图像的深度相同。kernel---内核也就是卷积核。矩阵。注意array np.array[[0, 0, 0], [0, 1, 0], [0, 0, 0]]是一个恒等核根据上述卷积计算可知经过恒等核过滤后的目标图像与源图像是一样的外观上是一样的。 import cv2import numpy as np car  cv2.imread(image\\car.jpg)# 创建恒等核kernel1  np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]])# 使用filter2D()函数执行线性滤波操作smooth_car  cv2.filter2D(car, ddepth-1, kernelkernel1)combine  np.hstack((car, smooth_car))# 显示原始图像和经过恒等核过滤后的图像cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey(0)cv2.imwrite(image\\smooth_car.jpg, smooth_car)cv2.destroyAllWindows() 运行结果如下 import cv2import numpy as np car  cv2.imread(image\\car.jpg)# 创建算术平方根核kernel1  np.ones((3, 3), f4)/9# 使用filter2D()函数执行线性滤波操作smooth_car  cv2.filter2D(car, ddepth-1, kernelkernel1)combine  np.hstack((car, smooth_car))# 显示原始图像和经过恒等核过滤后的图像cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 6.2. 内置函数模糊图像 语法cv2.blur(src, ksize[, dst[, anchor[, borderType]]])---dst参数src---源图像。ksize---模糊函数的内核尺寸元组类型参数。dst---目标图像在python中无任何意义一般不传参或设成None。borderType---制作图形边界。注意该函数与使用算术平方根核模糊的图像结果完全相同。 import cv2import numpy as np car  cv2.imread(image\\car.jpg)smooth_car  cv2.blur(car, ksize(3, 3))combine  np.hstack((car, smooth_car))cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 6.3. 高斯模糊 高斯模糊使用了高斯滤波器即使用高斯又称正太分布作为滤波函数该滤波器执行加权平均值根据像素值与内核中心的距离对像素值进行加权离中心较远的像素对加权平均值的影响较小。语法cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])---dst参数src---源图像。ksize---高斯核的尺寸元组类型参数一般设置为奇数方阵。sigmaX---X方向上的高斯核标准差。dst---目标图像在python中无任何意义一般不传参或设成None。sigmaY---Y方向上的高斯核标准差。sigmaY0表示sigmaYsigmaXsigmaY0sigmaX0表示X和Y方向的高斯核标准差需要根据ksize.width、ksize.height计算为了完全控制结果建议指定ksize、sigmaX和sigmaY的值。borderType---制作图形边界。 import cv2import numpy as np car  cv2.imread(image\\car.jpg)gaussian_blur_car  cv2.GaussianBlur(car, (3, 3), sigmaX1, sigmaY0)combine  np.hstack((car, gaussian_blur_car))cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey(0)cv2.imwrite(image\\gaussian_blur_car.jpg, gaussian_blur_car)cv2.destroyAllWindows() 运行结果如下 6.4. 中值模糊 中值模糊是在源图像中的每个像素都替换为内核区域中图像像素的中值。语法cv2.medianBlur(src, ksize[, dst])---dst参数src---源图像。ksize---内核的大小其必须是大于1的奇数。注意对于相同的内核大小中值模糊的效果比高斯模糊更突出。 import cv2import numpy as np car  cv2.imread(image\\car.jpg)median_blur_car  cv2.medianBlur(car, 3)combine  np.hstack((car, median_blur_car))cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 6.5. 自定义内核锐化图像 我们也可以利用卷积核锐化图像其实现依赖于cv2.filter2D()函数。 import cv2import numpy as np car  cv2.imread(image\\car.jpg)# 创建锐化内核归一化处理保持亮度不变kernel1  np.array([[0, -1, 0], [-1, 3, 0], [0, 0, 0]])# 使用filter2D()函数执行线性滤波操作sharp_car  cv2.filter2D(car, ddepth-1, kernelkernel1)combine  np.hstack((car, sharp_car))# 显示原始图像和经过自定义内核锐化后的图像cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey(0)cv2.imwrite(image\\sharp_car.jpg, sharp_car)cv2.destroyAllWindows() 运行结果如下 6.6. 图像的双边滤波 通常单一使用图像模糊或锐化是达不到预期效果的此时我们可以选择使用双边滤波方法让二者共同作用在图像中。双边滤波本质上是对图像应用2D高斯模糊且考虑了相邻像素强度的变化(用以降低边缘区域的高斯权重)。让我们先来探讨下双边滤波的工作过程。假如我们正在过滤图像中靠近边缘的区域普通的高斯模糊会根据实际权重模糊边缘但是双边滤波器可以通过感知边缘通过像素强度的差异主动降低边缘区域的权重从而减少高斯模糊对边缘的影响。因此像素强度更均匀的区域更加模糊边缘区域几乎无模糊。图像中的过滤像素的最终值是由空间和强度权重决定因此 相似且接近过滤像素的像素将产生不同程度的影响根据高斯权重远离过滤像素的像素影响较小由于高斯权重过滤像素附近的像素强度差异越大影响越小即使很靠近过滤像素。 opencv中利用cv2.bilateraFilter()函数实现双边过滤。语法cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])---dst参数src---源图像。d---定义用于过滤的像素邻域的直径。sigmaColor---颜色像素强度标准差定义一维高斯分布该分布指定允许的像素强度变化的程度。sigmaSpace---x和y轴组成的空间的标准差。borderType---制作图形边界。 import cv2import numpy as np car  cv2.imread(image\\car.jpg)bilateral_filter_car  cv2.bilateralFilter(car, d5, sigmaColor40, sigmaSpace50)combine  np.hstack((car, bilateral_filter_car))# 显示原始图像和经过自定义内核锐化后的图像cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 7. 图像阈值处理 阈值又叫临界值是指一个效应能够产生的最低值或最高值。图像的阈值是指灰度阈值是针对灰度图像的。阈值处理是指剔除图像内像素值高于阈值或低于阈值的像素点。利用图像阈值可以实现图像分割即阈值分割法。根据阈值分割规则的作用区域可分为全局阈值分割和局部阈值分割两种。全局阈值分割方法包括直方图计数法、熵算法、Otsu算法局部阈值分割是指自适应阈值法。语法cv2.threshold(src, thresh, maxValue, type[, dst])---retval, dst参数src---源图像。thresh---阈值。maxValue---与cv2.THRESH_BINARY和cv2.THRESH_BINARY_INV阈值类型一起使用的最大值。type---阈值类型。cv2.THRESH_BINARY、cv2.THRESH_BINARY_INY、cv2.THRESH_TRUNC、cv2.THRESH_TOZERO、cv2.THRESH_TOZERO_INV、cv2.THRESH_MASK、cv2.THRESH_OTSU、cv2.THRESH_TRIANGLE。返回值retval---阈值。dst---目标图像。这里只简单的演示使用cv2.THRESH_BINARY阈值类型的示例仅作为入门了解。 import cv2import numpy as np # 需要对图像做预处理——转化为灰度图src  cv2.imread(image\\cat.jpg, cv2.IMREAD_GRAYSCALE)retval, dst  cv2.threshold(src, 100, 255, cv2.THRESH_BINARY)print(retval)combine  np.hstack((src, dst))cv2.imshow(original image on the left, smooth image on the right, combine)cv2.waitKey()cv2.destroyAllWindows() 运行结果如下 8. Blob检测 Blob译文是“颜色的一小片斑点”。它是图像中拥有共同属性例如灰度值的连通域上图中的Blob就是灰色的连通域。Blob检测就是为了识别并标记这些连通域。就上图而言使用Blob检测可以达到如下效果 Blob检测是通过cv2.SimpleBlobDeterctor算子实现的。 8.1. Blob检测是如何工作的 阈值化(Thresholding)通过对源图像进行阈值化将源图像转换为若干二值图像。阈值从minThreshold开始以thresholdStep为间隔递增直到maxThreshold。分组(Grouping)对每份二值图像提取连通域。合并(Merging)计算每个连通域的中心并合并距离小于minDistBetweenBlobs的连通域。返回(Returning)计算并返回 新合并的连通域的中心和半径。 8.2. 按颜色、大小和形状筛选Blob 按颜色首先需要明确需要颜色参数筛选Blob即设置filterByColor1(或True)。其次设置颜色倾向blobColor0以选择较暗的blobblobColor255以选择较浅的区域。按大小首先需要明确需要大小参数筛选Blob即设置filterByArea1(或True)。其次设置minArea和maxArea的适当值。例如设置minArea50maxArea234将滤除所有少于50和多于234个像素点的blob。按形状在opencv中形状由三个参数控制圆度Circularity、凸度Convexity、惯性比Inertia Ratio。圆度Blob与圆的接近程度其计算公式为 image.png 。例如正六边形的圆度大于正方形的。圆的圆度为1正方形的为0.785。首先设置filterByCircularity1或True然后设置适当的minCircularity和maxCircularity。 凸度Blob面积/凸包面积。首先设置filterByConvexity1或True然后设置适当的minConvexity和maxConvexity(两值在[0, 1]范围)。惯性比对于一个圆该值是1对于椭圆它是0和1之间而对于线是0。首先设置filterByInertia1或True然后设置适当的minInertiRatio和maxInertiRatio(两值在[0, 1]范围)。 8.3. 设置cv2.SimpleBlobDeterctor参数 # 导入库import cv2import numpy as np # 读取图像im  cv2.imread(image\\blob.jpg, cv2.IMREAD_GRAYSCALE) # 设置SimpleBlobDetector参数params  cv2.SimpleBlobDetector_Params() # 改变阈值params.minThreshold  10params.maxThreshold  200 # 根据面积过滤params.filterByArea  Trueparams.minArea  1500 # 根据Circularity过滤params.filterByCircularity  Trueparams.minCircularity  0.1 # 根据Convexity过滤params.filterByConvexity  Trueparams.minConvexity  0.87 # 根据Inertia过滤params.filterByInertia  Trueparams.minInertiaRatio  0.01 # 创建一个带有参数的检测器# opencv3.0前的版本使用cv2.SimpleBlobDetector()创建检测器# 3.0之后的版本使用cv2.SimpleBlobDetector_create()创建ver  cv2.__version__.split(.)if int(ver[0])  3: detector  cv2.SimpleBlobDetector(params)else: detector  cv2.SimpleBlobDetector_create(params) # 检测blobskeypoints  detector.detect(im) # 用红色圆圈画出检测到的blobs# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS 确保圆的大小对应于blob的大小im_with_keypoints  cv2.drawKeypoints(im, keypoints, np.array([]), (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) # 结果显示cv2.imshow(Keypoints, im_with_keypoints)cv2.waitKey(0) 运行结果如下 这里需要补充一个函数cv2.drawKeypoints()即绘制特征关键点函数。语法cv2.drawKeypoints(image, keypoints, outImage[, color[, flags]])--outImage参数image---源图像。keypoints---特征点向量向量内每个元素是一个keypoint对象它包含了特征点的各种属性信息。outImage---特征点绘制的画布对象可以是原始图像。color---绘制的特征点的颜色信息默认绘制的是随机彩色。flags---特征点的绘制模式有以下几种模式可选。 ①DRAW_MATCHES_FLAGS_DEFAULT只绘制特征点的坐标点显示在图像上就是一个个小圆点每个圆点的坐标都是特征点的坐标。②DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG函数不创建输出的图像而是直接在输出图像变量空间绘制要求本身输出图像变量就是一个初始化好了的size与type都是已经初始化好的变量。③DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS 单点的特征点不被绘制。④DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS绘制特征点的时候绘制的是一个个带有方向的圆这种方法同时显示图像的坐标size和方向是最能显示特征的一种绘制方式。 9. 边缘检测 边缘检测是一种重要的图像处理技术用于确定图片中物体的边界边缘或区域。边缘检测算法广泛应用于生产工作中的计算机视觉算法处理流水线中。在进行检测前需要进行预处理①边缘检测主要是依靠图像的像素强度来判别是否为边缘因此需要将图像转为灰度图。②在对图像进行边缘检测之前需要进行平滑处理以减少图像中的噪点。这是因为在边缘检测中需要计算像素强度的数值导数而噪点会产生不必要的干扰。这里我们介绍两种重要的边缘检测算法Sobel边缘检测和Canny边缘检测。 9.1. Sobel边缘检测 关于Sobel检测的原理可参看Edge Detection Using OpenCV | LearnOpenCV #语法cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])---dst参数src---源图像。ddepth---输出图像的位深度。dx---x方向的求导阶数。dy---y方向的求导阶数。ksize---Sobel卷积核的尺寸必须是奇数。 import cv2 image  cv2.imread(image\\tiger.png, cv2.IMREAD_GRAYSCALE)# 平滑图像image_blur  cv2.GaussianBlur(image, (3, 3), sigmaX1, sigmaY0)# Sobel算子1dx1dy0sobel_x  cv2.Sobel(image_blur, cv2.CV_64F, dx1, dy0, ksize3)# Sobel算子2dx0dy1sobel_y  cv2.Sobel(image_blur, cv2.CV_64F, dx0, dy1, ksize3)# Sobel算子3dx1dy1sobel_xy  cv2.Sobel(image_blur, cv2.CV_64F, dx1, dy1, ksize3) cv2.imshow(Sobel X, cv2.resize(sobel_x, None, fx0.6, fy0.6))cv2.waitKey(0) cv2.imshow(Sobel Y, cv2.resize(sobel_y, None, fx0.6, fy0.6))cv2.waitKey(0) cv2.imshow(Sobel XY, cv2.resize(sobel_xy, None, fx0.6, fy0.6))cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 9.2. Canny边缘检测 关于Canny检测的原理可参看Edge Detection Using OpenCV | LearnOpenCV #语法cv2.Canny(image, threshold1, threshold2[, edges[, apertureSie[, L2gradient]]]])---dst参数image---8位的图像。threshold1---阈值1强度小于此阈值的像素将被排除。threshold2---阈值2强度大于此阈值的像素将于实体边相关联。 import cv2 image  cv2.imread(image\\tiger.png, 0)# 平滑图像image_blur  cv2.GaussianBlur(image, (3, 3), sigmaX1, sigmaY0)edges  cv2.Canny(image_blur, 75, 200)cv2.imshow(Canny Edge Detection, edges)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 10. 轮廓检测 轮廓检测可以检测物体的边界并在图像中轻松定位它们。它可以被应用到图像前景提取、简单图像分割、检测和识别等工作中。等高线指具有相同颜色和强度的边界像素点连接而成的闭合线路也就是轮廓。在opencv中我们可以使用cv2.findContours()和cv2.drawContours()在图像中查找和绘制轮廓。在查找轮廓时常用两种检测算法cv2.CHAIN_APPROX_NONE、cv2.CHAIN_APPROX_SIMPLE。 10.1. 轮廓检测的步骤 读取图像并将其转换为灰度格式。这是由于轮廓检测是以阈值检测为基础的而阈值又是针对灰度图而言的。应用二值图像。利用阈值检测或Canny检测将灰度图转化为二值图并将此二值图输入到查找轮廓算法中。查找轮廓。使用cv2.findContours()函数检测图像轮廓。绘制轮廓。使用cv2.drawContours()函数绘制图像轮廓。 10.2. 轮廓检测的实现 首先我们先来了解两个函数cv2.findContours()和cv2.drawContours()。 cv2.findContours()语法cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])---contours, hierarchy参数image---二值图像。mode---轮廓检索模式。包括cv2.RETR_EXTERNAL、cv2.RETR_LIST、cv2.RETR_CCOMP、cv2.RETR_TREE。示例中我们将使用cv2.RETR_TREE这意味着将从二值图像中检索所有可能的轮廓。method---轮廓近似方法。常用cv2.CHAIN_APPROX_NONE和cv2.CHAIN_APPROX_SIMPLE。cv2.CHAIN_APPROX_NONE存储所有的等高点cv2.CHAIN_APPROX_SIMPLE压缩水平、垂直和对角线段仅保留其端点。例如举行轮廓使用4个角点进行编码。hierarchy---层次结构。offset---偏移。返回contours---轮廓线。hierarchy---层次结构。 cv2.drawContours()语法cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])---image参数image---要在其上绘制轮廓的图像。contours---从cv2.findContours()函数获得的轮廓线。contoursIdx---等值线点的像素坐标列在获得的等值线中。使用此参数可以指定此列表中的索引位置以准确指示要绘制的轮廓点。提供负值将绘制所有等值线点。color---要绘制的轮廓线的颜色。thickness---要绘制的轮廓线的粗细若为负数则填充轮廓线内部。 import cv2 apple  cv2.imread(image\\apple.jpg)image  cv2.cvtColor(apple, cv2.COLOR_BGR2GRAY)image_copy  apple.copy() retval, dst  cv2.threshold(image, 100, 255, cv2.THRESH_BINARY)contours, hierarchy  cv2.findContours(dst, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)cv2.drawContours(imageimage_copy, contourscontours, contourIdx-1, color(0, 255, 0), thickness2) cv2.imshow(111, image_copy)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 import cv2 apple  cv2.imread(image\\apple.jpg)image  cv2.cvtColor(apple, cv2.COLOR_BGR2GRAY)image_copy  apple.copy() retval, dst  cv2.threshold(image, 100, 255, cv2.THRESH_BINARY)contours, hierarchy  cv2.findContours(dst, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)cv2.drawContours(imageimage_copy, contourscontours, contourIdx-1, color(0, 255, 0), thickness2) cv2.imshow(111, image_copy)cv2.waitKey(0)cv2.destroyAllWindows() 运行结果如下 可以看到cv2.CHAIN_APPROX_NONE和cv2.CHAIN_APPROX_SIMPLE的输出之间几乎没有差异。这是为什么呢这归功于 cv2.drawContours()函数。尽管cv2.CHAIN_APPROX_SIMPLE方法通常生成的点较少但 cv2.drawContours()函数会自动连接相邻的点即使它们不在轮廓列表中也会连接它们。 10.3. 轮廓的层次结构 层次结构hierarchy表示等高线轮廓线之间的父子关系在轮廓检测中轮廓检索模式mode对生成的轮廓层次结构产生影响。为什么要引入层次结构概念呢这是因为我们既需要描绘图像中单个对象的轮廓也需要描绘对象和其内部的轮廓。 通过上图中的几个形状和线条我们可以很好的了解层次结构不同的数字显示了不同形状之间的层次结构。 根据等高线层次结构和父子关系所有单独的数字即 1、2、3 和 4都是单独的对象。我们可以说3a是3的孩子。请注意3a 表示轮廓 3 的内部部分。等高线 1、2 和 4 都是父形状没有任何关联的子形状因此它们的编号是任意的。换句话说轮廓 2 可以标记为 1反之亦然。 cv2.findContours()函数返回的hierarchy层次结构是一个三维数组该数组中的每个层次结构包含了四个值分别是Next, Previous, First_Child, Parent。Next---表示当前轮廓的下一个处于同一层次结构级别的轮廓索引。上图中等高线1与2的结构级别处于同一层次结构级别上因此1 Next--- 2没有与等高线3处于同一层次结构级别的等高线因此3 Next--- -1。Previous---表示当前轮廓的上一个处于同一层次结构级别的轮廓索引。First_Child---表示当前轮廓的第一个子轮廓索引。上图中等高线3的子轮廓是3a因此3 First_Child--- 3a。Parent---表示当前轮廓的父等高线的索引。 不同轮廓检索模式下的轮廓层次结构和轮廓线mode cv2.RETR_LISTRETR_LIST模式不会在提取的轮廓之间创建任何父子关系因此对于检测到的所有等高线的First_Child与Parent的值都是-1。 import cv2 image2  cv2.imread(image\\shape.jpg)image  cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) retval, thresh2  cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)contours5, hierarchy5  cv2.findContours(thresh2, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)image_copy6  image2.copy()cv2.drawContours(image_copy6, contours5, -1, (0, 255, 0), 2, cv2.LINE_AA) cv2.imshow(RETR_LIST, image_copy6)print(fRETR_LIST: \n{hierarchy5})cv2.waitKey(0)cv2.imwrite(image\\contours_retr_list.jpg_LIST.jpg, image_copy6)cv2.destroyAllWindows()RETR_LIST: [[[ 1 -1 -1 -1]  [ 2  0 -1 -1]  [ 3  1 -1 -1]  [ 4  2 -1 -1]  [-1  3 -1 -1]]] 生成图如下 mode cv2.RETR_EXTERNALRETR_EXTERNAL模式仅检测父轮廓并忽略任何子轮廓因此所有的内部轮廓如 3a 和 4都不会被绘制。 import cv2 image2  cv2.imread(image\\shape.jpg)image  cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) retval, thresh2  cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)contours5, hierarchy5  cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)image_copy6  image2.copy()cv2.drawContours(image_copy6, contours5, -1, (0, 255, 0), 2, cv2.LINE_AA) cv2.imshow(RETR_EXTERNAL, image_copy6)print(fRETR_EXTERNAL: \n{hierarchy5})cv2.waitKey(0)cv2.imwrite(image\\contours_retr_external.jpg, image_copy6)cv2.destroyAllWindows()RETR_EXTERNAL: [[[ 1 -1 -1 -1]  [ 2  0 -1 -1]  [-1  1 -1 -1]]] 生成图如下 mode cv2.RETR_CCOMPRETR_CCOMP模式建立了两级层次结构即轮廓线不是第一级层次结构就是第二级层次结构若有嵌套的轮廓线则2N1N是非负整数是第一级层次结构。如下图所示 import cv2 image2  cv2.imread(image\\shape.jpg)image  cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) retval, thresh2  cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)contours5, hierarchy5  cv2.findContours(thresh2, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)image_copy6  image2.copy()cv2.drawContours(image_copy6, contours5, -1, (0, 255, 0), 2, cv2.LINE_AA) cv2.imshow(RETR_CCOMP, image_copy6)print(fRETR_CCOMP: \n{hierarchy5})cv2.waitKey(0)cv2.imwrite(image\\contours_retr_ccomp.jpg, image_copy6)cv2.destroyAllWindows()RETR_CCOMP: [[[ 1 -1 -1 -1]  [ 3  0  2 -1]  [-1 -1 -1  1]  [ 4  1 -1 -1]  [-1  3 -1 -1]]] 生成图如下 mode cv2.RETR_TREERETR_TREE模式创建完整的层次结构级别不限于两级其视情况而定。 import cv2 image2  cv2.imread(image\\shape.jpg)image  cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY) retval, thresh2  cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)contours5, hierarchy5  cv2.findContours(thresh2, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)image_copy6  image2.copy()cv2.drawContours(image_copy6, contours5, -1, (0, 255, 0), 2, cv2.LINE_AA) cv2.imshow(RETR_TREE, image_copy6)print(fRETR_TREE: \n{hierarchy5})cv2.waitKey(0)cv2.imwrite(image\\contours_retr_tree.jpg, image_copy6)cv2.destroyAllWindows()RETR_TREE: [[[ 3 -1  1 -1]  [-1 -1  2  0]  [-1 -1 -1  1]  [ 4  0 -1 -1]  [-1  3 -1 -1]]] 生成图如下 不同轮廓检索方式的运行时间比较 轮廓检索方式 运行时间 (s) cv2.RETR_LIST 0.000382 cv2.RETR_EXTERNAL 0.000554 cv2.RETR_CCOMP 0.001845 cv2.RETR_TREE 0.005594 cv2.RETR_LIST和cv2.RETR_EXTERNAL执行所需的时间最少因为cv2.RETR_LIST没有定义任何层次结构cv2.RETR_EXTERNAL只检索父轮廓cv2.RETR_CCOMP执行时间第次之它检索所有轮廓并定义两级层次结构。cv2.RETR_TREE执行所需的时间最长因为它会检索所有轮廓并为每个父子关系定义独立的层次结构级别。 11. 参考内容
http://www.pierceye.com/news/590655/

相关文章:

  • 国外申请域名的网站百度标记号码认证平台
  • 专门做淘宝代运营的网站支付建设网站的费用什么科目
  • 天津企业设计网站建设建个网站做外贸
  • 申请永久网站空间wordpress论坛采集
  • 网站如何做竞价佛山新网站建设机构
  • 网站建设费可以一次性冲费用吗学校门户网站作用
  • 手机上怎么制作网站音乐网站如何建立
  • 新乡企业网站建设公司寮步东莞网站建设
  • wordpress中国网站排名如何加入广告联盟赚钱
  • 济宁网站建设培训学校wordpress导入表单
  • 做农产品交易网站阿里云已备案域名购买
  • 免费建站网站一级大录像不卡谁给我一个企业邮箱认证
  • 中国做网站东台做网站公司
  • 建设数据库网站需要哪些设备wordpress多功能主题 cosy
  • 苏州市郭巷建设局网站一家专门做鞋子的网站
  • 光明网站建设网站建设成果
  • 商业网站建设举例宝塔做两个网站6
  • 网站优化排名分享隐迅推前端开发入门培训
  • 曲周县建设局网站东莞保安公司电话
  • 合肥商城网站建设多少钱wordpress页面代码怎么改
  • 前期做网站宣传费用怎样做账企业网站建设的劣势
  • 网站建设企业哪家好做网站三大主流框架
  • 网站托管服务方案珲春建设局网站
  • 开发网站公司收入重庆多功能网站建设
  • 河北手机网站建设上海网站seo招聘
  • 厦门市建设局思明建设分局官方网站在谷歌上做外贸网站有用吗
  • 网站开发手机自适应直接在原备案号下增加新网站
  • 公司网站建设安全的风险网络工程师app
  • 网站app封装怎么做电商网页
  • 网站文章做排名wordpress菜单文本