• [问题求助] Atlas 200 dk dd镜像如何卸载预装的opencv-python
    【功能模块】Atlas 200 dk通过dd镜像搭建合设环境:固件与驱动版本:1.0.12 CANN版本:5.0.4alpha005其中预装了opencv-python,请问是通过什么途径装上的,该如何彻底卸载,需要的版本和这个不一样【操作步骤&问题现象】1、2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] Atlas 200 DK用opencv调用树莓派V2摄像头案例
    【功能模块】Atlas 200 DK 用opencv(python)调用树莓派V2摄像头(element i4)的案例哪里有呀,手写代码运行不成功,想找个参考【操作步骤&问题现象】1、2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] Atlas 200 DK 安装opencv(python)
    【功能模块】Atla 200 DK安装opencv(python)卡在了[ 92%] Building CXX object modules/gapi/CMakeFiles/opencv_perf_gapi.dir/perf/cpu/gapi_imgproc_perf_tests_fluid.cpp.o,在此处卡住将近一个小时了,按ctrl+c后停止了【操作步骤&问题现象】1、按照https://bbs.huaweicloud.com/forum/thread-28405-1-1.html中的教程安装的,如图12、错误截图如图2【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [安装] 昇腾AI设备安装开发环境,同时将此环境作为运行环境的samples相关依赖安装 ,opencv安装失败
    【功能模块】【操作步骤&问题现象】1、第三方环境配置 opencv安装失败,怎么解决2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] OpenCV图像噪声与去噪函数方法对比使用介绍【转载】
    一:噪声类型与去噪声方法介绍图像去噪在二值图像分析、OCR识别预处理环节中十分重要,最常见的图像噪声都是因为在图像生成过程中因为模拟或者数字信号受到干扰而产生的,常见的噪声类型有如下:椒盐噪声高斯噪声泊松噪声乘性噪声OpenCV中有多个可以降低图像噪声、对图像实现平滑滤波的函数,最常见的就是均值模糊与高斯模糊,它们都可以在一定程度上减低上述几种噪声,另外还有中值模糊、双边模糊、非局部去噪等函数方法可以使用,针对特定种类的噪声,使用有针对性函数与合理的参数可以取得较好的效果:函数名称 去噪效果blur对各种噪声都有一定的抑制作用GaussianBlur对随机噪声比较好,对椒盐噪声效果不好medianBlur对椒盐噪声效果比较好fastNlMeansDenoising非局部去噪,速度很慢,可以调参的去噪方法fastNlMeansDenoisingColored同上,去噪针对彩色图像对于fastNIMeansDenoising方法来说,只支持输入是灰度图像的,各个参数意义如下:fastNlMeansDenoising ( src // 输入图像 dst = None , // 输出结果 h = None , // h值越大表示去噪声力度越大,同时细节丢失也越多,默认10即可。 templateWindowSize = None , // 相似性权重计算窗口大小,一般为5~15之间 searchWindowSize = None // 搜索窗口,大小可以设置为相似性计算窗口大小的3~5倍即可。Python版本源代码如下:1. `def denoise_demo():` 2. `src = cv.imread("D:/javaopencv/lenanoise2.png")` 3. `cv.imshow("input", osrc)` 4. `# 相似窗口大小5, 搜索窗口大小25` 5. `# h = 10, h 越大表示去噪声效果越好,细节越丢失` 6. `dst = cv.fastNlMeansDenoisingColored(src, None, 15, 15, 7, 21)` 8. `gray= cv.cvtColor(src, cv.COLOR_BGR2GRAY)` 9. `gret = cv.fastNlMeansDenoising(gray, None, 15, 8, 25)` 10. `cv.imshow("denoise", dst)` 11. `cv.imshow("result", gret)` 12. `cv.imwrite("D:/nim_result.png", dst)` 15. `def salt_pepper_noise():` 16. `src = cv.imread("D:/javaopencv/lenanoise.png")` 17. `cv.imshow("input", osrc)` 18. `# ksize必须是大于1 奇数3\5\7\9\11` 19. `dst = cv.medianBlur(src, 5)` 20. `cv.imshow("denoise", dst)` 21. `cv.imwrite("D:/sp_result.png", dst)`从上面可以看出,对椒盐噪声中值滤波效果比较好,对高斯噪声非局部均值去噪效果比较好!为山者基于一篑之土,以成千丈之峭转载于: OpenCV学堂作者: gloomyfish
  • [技术干货] 使用OpenCV,构建文档扫描仪
    本文将使用 OpenCV,创建一个简单的文档扫描仪,就像常用的摄像头扫描仪应用程序一样。这个想法很简单,因为我们认为文档是四边形,我们获取边缘的位置并使用它来抓取文档本身,而忽略无用的图像背景。简单的管道:加载图像>>检测边缘和抓取位置>>使用图像上的位置导入包首先,我们导入处理图像可能需要的包。threshold_local 函数对你来说可能看起来很新,但这段代码其实没有什么特别之处。该函数来自 scikit 图像包。# import packagesfrom skimage.filters import threshold_localimport numpy as npimport cv2import imutils加载图像。在这里,我们加载图像并保留一份副本。在这里,原始的副本对于获得清晰且未经篡改的图像扫描非常重要。为了处理图像,我调整到一个合理的比例,接下来我对图像进行灰度化以减少颜色并使其模糊(即有助于从图像背景中去除高频噪声),这些都是为了找到文件的边缘。#load in the imageimage = cv2.imread("images/questions.jpg")orig  = image.copy()#Resize the image.height = image.shape[0]width = image.shape[1]ratio = 0.2width = int(ratio * width)height = int(ratio * height)image = cv2.resize(image,(width, height))#find edges in the image.gray_scaled = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#blurr the imagegray_scaled = cv2.GaussianBlur(gray_scaled,(5,5),0)#Edge detectionedged = cv2.Canny(gray_scaled,50, 200)cv2.imshow("Image", image)cv2.waitKey(0)cv2.imshow("Edges detected", edged)cv2.waitKey(0)找到轮廓。使用 cv2.findcontours() 找到轮廓。接下来,我们使用 imutils 库抓取轮廓,最后,我们根据最大轮廓区域,对抓取的轮廓进行排序。在这种情况下,我保留了最大的 5 个# find contours in the edged image. keep only the largest contours.contours = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)# grab contourscontours = imutils.grab_contours(contours)# select contours based on size.contours = sorted(contours, key=cv2.contourArea, reverse = True)[:5]对轮廓进行进一步处理。首先,我们遍历轮廓并找到周长,这是将周长近似为点所必需的。完成此操作后,我们最终搜索恰好具有 4 个点的轮廓,这很可能是近似矩形形状的纸张。完成后,我们获取这些点的坐标,然后将它们初始化为纸张轮廓。# loop over the contours.for contour in contours:   perimeter = cv2.arcLength(contour, True)   # approximate your contour   approximation = cv2.approxPolyDP(contour, 0.02*perimeter, True)      # if our contour has 4 points, then surely, it should be the paper.   if len(approximation) == 4:       paper_outline = approximation       break有了坐标,下一步就是画轮廓,很简单。# Draw the found contour.cv2.drawContours(image,[paper_outline],-1,(225,0,0),2)cv2.imshow("Found outline", image)cv2.waitKey(0)你心中的问题是,我们完成了吗?好吧,你可能会说是的,因为你在图像周围设置了很好的轮廓。答案是否定的,为了获得最佳扫描形式的图像,我们需要 90 度的图像视图,尤其是在倾斜的情况下。为此,我们将创建一个函数来处理此任务。管道:排列点>>标记点>>从真实图像中挑选点arrange_points 函数。这样做的方法非常简单,归功于 Adrian Rosebrock(博士)。这个函数背后的直觉是我们获取文档四个边缘的坐标,并将其安排到我们认为它应该在的位置,我花了一些时间给出描述的图形表示。点坐标的和1)从上图中我们可以看出,点坐标(X,Y)的和最大的是在右上角。2)最小的点总和是左下点。点坐标的差3)点坐标的差的最大值是左上角4)点坐标的差的最小值是左下角。代码。该函数接受参数points,接下来,我初始化一个 NumPy 数组来表示矩形,该数组是一个 4 x 2 矩阵,因为我们有 4 个点和 2 个坐标(X,Y)。最后,如上所述,我在矩形的点中注册(点的和以及点的差)。最后,我正确地返回了 Rectangle 的坐标。def arrange_points(points):   # initialize a list of co-ordinates that will be ordered   # first entry is top-left point, second entry is top-right   # third entry is bottom-right, forth/last point is the bottom left point.   rectangle = np.zeros((4,2), dtype = "float32")      # bottom left point should be the smallest sum   # the top-right point will have the largest sum of point.   sum_points= points.sum(axis =1)   rectangle[0] = points[np.argmin(sum_points)]   rectangle[2] = points[np.argmax(sum_points)]         #bottom right will have the smallest difference   #top left will have the largest difference.   diff_points = np.diff(points, axis=1)   rectangle[1] = points[np.argmin(diff_points)]   rectangle[3] = points[np.argmax(diff_points)]         # return order of co-ordinates.   return rectangle设置四个点。这个功能很简单,这里的想法当然是拉直纸张,只提取需要的区域。在这里,输入是 1) 图像本身和点或坐标。首先,我们使用我们创建的第一个函数“arrange_points”来排列函数的点。接下来,我相应地分配了点,因为我之前已经安排了点并且也很好地命名了它们。计算。对于计算,只需两点之间的距离即可找到每边的长度。有了这个,我们能够在对的位置上防止错误地调整图像。顾名思义,目的地是图像的新视图。其中 [0,0] 表示左上角。接下来,[Max-width - 1,0] 表示右上角,我们还有 [maxwidth -1, maxheight-1] 表示底部右上角,最后是左下角 [0, max-height -1]。转换矩阵动作完成,工作结束,我们需要完成的是使用 cv2.getPerspectiveTransform() 的变换矩阵,它接受点的矩形和目的地。现在我们有了矩阵,我们使用 cv2.warpPerspective() 应用它,它获取你提供给函数的图像、变换矩阵,最后是建议扫描的(宽度和长度)。全部完成,返回转换后的图像# set four points.def set_four_points(image, points):   # obtain order of points and unpack.   rectangle = arrange_points(points)   (top_left,top_right,bottom_right,bottom_left) = rectangle   # let's compute width of the rectangle.   # using formular for distance between two points   left_height = np.sqrt(((top_left[0]-bottom_left[0])**2) + ((top_left[1]-bottom_left[1])**2))   right_height = np.sqrt(((top_right[0]-bottom_right[0])**2) + ((top_right[1]-bottom_right[1])**2))   top_width = np.sqrt(((top_right[0]-top_left[0])**2) + ((top_right[1]-top_left[1])**2))   bottom_width = np.sqrt(((bottom_right[0]-bottom_left[0])**2) + ((bottom_right[1]-bottom_left[1])**2))      maxheight = max(int(left_height), int(right_height))   maxwidth  = max(int(top_width), int(bottom_width))      destination = np.array([       [0,0],       [maxwidth -1,0],       [maxwidth -1, maxheight-1],       [0, maxheight - 1]], dtype = "float32")                matrix = cv2.getPerspectiveTransform(rectangle, destination)      warped = cv2.warpPerspective(image, matrix, (maxwidth,maxheight))      return warped应用函数我们已经创建了函数,因此我们将其应用于最初保存的原始图像。第二个输入是论文的大纲。我通过删除我在开始时所做的比例缩放,将纸张轮廓重新调整回原来的大小。要获得图像的黑白感觉,需要使用 Threshold local,但当然,如果你想要对图像进行彩色扫描,则根本不需要它。最后,我调整大小并显示。warped = set_four_points(orig, paper_outline.reshape(4,2)*(1/ratio))#warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)#threshold = threshold_local(warped, 11, offset=10, method="gaussian")#warped = (warped > threshold).astype("uint8") * 255#show the original and scanned imagesprint("Image Reset in progress")cv2.imshow("Original", cv2.resize(orig,(width, height)))cv2.imshow("Scanned",cv2.resize(warped,(width, height)))cv2.waitKey(0)干得好!!,你刚刚创建了自己的扫描仪应用程序。       原文标题 : 构建文档扫描仪
  • [技术干货] Python中OpenCV的基础知识
    从安装到基本图像处理OpenCV 是一个流行的开源库,可用于不同的编程语言,例如 Python、C++ 和 JavaScript。它提供了一套丰富的工具来处理和分析图像和视频,让你可以从调整单张图片的大小到构建复杂的对象识别应用程序。Python 编程语言除了被广泛用作大多数图像处理和计算机视觉应用程序的标准外,还允许以非常直接的方式将 OpenCV 安装在你的计算机中。在本教程中,我将向你展示使用 OpenCV 安装、设置和对图像执行一些基本操作所需的步骤,重点介绍有关该库背后概念的重要基础知识。值得一提的是,这些步骤是在基于 Linux 的操作系统中使用Python3执行的。因此,如果你使用不同的配置,则可能需要进行细微的更改。设置虚拟环境使用 Python 时,通常建议在虚拟环境中运行你的应用程序。这样做,你可以只安装运行应用程序所需的包,使其独立于系统的其余部分。如果你的计算机上仍然没有安装虚拟环境工具,我建议你安装以下工具。python3 -m pip install virtualenv安装后,你可以使用此工具创建新的虚拟环境。为此,导航到你想要的目录并运行以下命令。请注意,我为我的环境选择了名称 my_venv,但你可以选择任何你想要的名称。python3 -m venv my_venv最后,你只需要激活你的虚拟环境,以便你在此终端中运行的任何内容都将在其中完成。source my_venv/bin/activate安装 OpenCV首先更新你的包管理器并为 Python3 安装 OpenCV。sudo apt updatesudo apt install python3-opencv然后,使用 pip 在你的虚拟环境中安装 OpenCV。pip install opencv-python打开图像使用你最喜欢的 IDE,创建一个扩展名为 .py 的新文件,然后从导入 OpenCV 类开始import cv2我们在这里做的第一件事是使用 imread() 方法加载图像并使用 imshow() 方法打开它。请将下面的路径替换为你的图片所在的路径。image = cv2.imread("images/messi.jpg")cv2.imshow("Original image", image)原始图像关于 OpenCV 如何解释图像的第一个有趣的点是,imread()返回一个n 维数组对象。对于 RGB 图像,例如本例中使用的图像,此数组具有以下形状:[宽×高×通道数]你可以通过打印图像形状来确认这一点。print("Original image shape:", image.shape)更改图像色彩空间颜色空间是用于描述图像的光谱上的一系列颜色。尽管有多种颜色空间可用,但最常见的是 RGB 和灰度。OpenCV 包含一种特殊的颜色空间转换方法。为了将图像从 RGB 转换为灰度,你需要应用 cvtColor()方法。image_grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)cv2.imshow(“Grayscale image”, image_grayscale)灰度图像重要的是要注意,现在你的图像不再包含三个维度。那是因为对应于通道的第三维在灰度色彩空间中没有使用。print("Grayscale image shape:", image_grayscale.shape)编辑图像通道返回到包含三个颜色通道的原始图像,你现在可以操纵每个通道的强度值,以抑制或突出显示特定通道。与通常假设的相反,RGB 通道的访问顺序与首字母缩写词中的顺序不同。在 OpenCV 中,通道实际上以 BGR 格式提供:0 = B(蓝色)1 = G(绿色)2 = R(红色)在下面的示例中,我检索前两个通道中的所有像素并将它们设为零,这样绿色和蓝色通道将不会对生成的图像产生任何影响,因此图像将呈现完全红色调。image_red = image.copy()image_red[:, :, :2] = 0 cv2.imshow("Red image", image_red)具有空蓝色和绿色通道的图像打印红色图像形状时,请注意仍然存在第三维,否则生成的图像将被描述为灰度print("Red image shape:", image_red.shape)旋转图像除了颜色之外,还可以对图像形状进行操作,例如大小和方向。你可以从获取图像尺寸开始,就像 NumPy 对象一样。width, height, _ = image.shape然后可以通过取其宽度和高度的一半来计算图像的中心点。center = (width//2, height//2)为了旋转图像,你首先必须创建一个旋转矩阵,分别将中心点、所需的旋转度数和图像比例作为参数传递。使用不同于 1 的比例会改变图像大小。rotation_matrix = cv2.getRotationMatrix2D(center, 45, 1.0) 旋转矩阵对象本身不足以做我们想要的。它作为参数传递给 warpAffine() 方法,这是实际执行旋转的方法。image_rotated = cv2.warpAffine(image, rotation_matrix, (width, height))cv2.imshow(“Rotated image”, image_rotated)旋转图像调整图像大小你可以使用之前获得的高度和宽度值来定义图像的新尺寸。在下面的示例中,我将它们设置为将图像缩小到其原始大小的三分之一。new_size = (width//3, height//3)负责调整图像大小的方法是resize(),它分别需要原始图像对象、所需的新大小和插值方法作为参数。image_resized = cv2.resize(image, new_size, interpolation=cv2.INTER_LINEAR)cv2.imshow(“Resized image”, image_resized)调整大小的图像然后,你可以检查调整大小的图像的尺寸。print(“Resized image shape:”, image_resized.shape)将绘图插入图像在某些应用程序中,可能需要向图像添加标记。OpenCV 类提供了多种在其上绘制线条和形状的方法。如下添加一行。这里的参数是原始图像、初始位置、最终位置、线条颜色 RGB 代码和线条宽度。请注意,实际上使用的是原始图像的副本,因为绘图方法会影响原始图像。image_line = cv2.line(image.copy(), (0, 0), (height//2, width//2), (0, 255, 255), 10)cv2.imshow(“Image with line”, image_line)带线条的图像同样,在图像中绘制矩形也有特定的方法。在这种情况下,第二个和第三个参数是矩形相对顶点的位置(左上角和右下角)。image_rectangle = cv2.rectangle(image.copy(), (500, 150), (900, 550), (0, 255, 255), 5)cv2.imshow(“Image with rectangle”, image_rectangle)带有矩形的图像你还可以通过将圆的中心位置和半径分别指定为第二个和第三个参数来绘制一个圆。image_circle = cv2.circle(image.copy(), (300, 300), 200, (0, 255, 255), 5)cv2.imshow(“Image with circle”, image_circle)带圆的图像       原文标题 : Python中OpenCV的基础知识
  • [问题求助] 【atlas200DK】【调用摄像头】摄像头返回的图片无法用于opencv及dlib库
    【功能模块】cameracapture【操作步骤&问题现象】1、调用cap.read返回的图片不能直接用于opencv,不是jpeg,怎么将他转换为jpeg,或者怎么将它用于opencv2、【截图信息】使用print获取的图片类型【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 【A200 DK】编译安装opencv的依赖安装不上
    【功能模块】编译安装opencv【操作步骤&问题现象】1、sudo apt-get install -y gcc g++ make cmake zlib1g zlib1g-dev libbz2-dev openssl libsqlite3-dev libssl-dev libxslt1-dev libffi-dev unzip pciutils net-tools libblas-dev gfortran libblas3 libopenblas-dev libncursesw5-dev 这些依赖安装不上,已经换了华为源、中科院源、阿里源尝试了【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] 如何使用OpenCV和DLIB在图像上操作人脸?
    这是一个关于如何使用OpenCV和DLIB在图像上应用虚拟唇膏的快速教程。同样的原理也可以推广到其他面部特征,比如某人的眼睛、鼻子、下巴……。为了获得上图所示的结果,我们需要执行以下一系列步骤:检测面部标志使用由嘴标志组成的凸多边形创建掩码使用形态学操作增强掩码,并使其模糊,以获得更好的混合效果隔离嘴唇和脸部将颜色变换应用于嘴唇把嘴唇和脸放在一起首先要做的是检测人脸的面部标志。库Dlib提供了一种方便的方法来实现这一点;但是,请记住,被摄对象的面部需要面对摄影机。如果头部姿势不正确,检测结果将不好。在这个例子中,我们只对嘴唇的点感兴趣。下图显示了Dlib返回的面部标志点的索引。如你所见,我们对48点到60点(嘴唇的外部“轮廓”)感兴趣。利用这些点,我们可以制作一个掩码,让我们在不影响面部整体外观的情况下处理嘴唇的颜色。但是,等一下。在开始操作这些颜色之前,我们需要改进掩码。在这个例子中,一个带有4x4矩形内核的形态学闭合操作就足够了。注意下面的图片,这个步骤填补了由cv2生成的原始多边形右上角的一个空白。右:使用唇部创建的凸多边形/左:关闭操作后的多边形为了获得自然的效果,我们还需要模糊掩码。模糊掩码将产生更好的混合效果。我们将cv2.GaussianBlur应用于掩码。最后,我们反转掩码(我们需要两个,一个用于嘴唇,一个用于面部)。右:模糊掩码/左:模糊反向掩码我们将应用这些掩码,方法是将它们从0–255(uint8)转换为0–1(float)范围,然后将它们与图像相乘。右下方的图像是原始图像乘以反转掩码。左侧的图像是原始图像上的颜色变换乘以掩码的结果。颜色变换由cv2.applyColorMap(im, cv2.COLORMAP_INFERNO)给出。右:原始图像和反向模糊掩码的位与运算/左:颜色变换图像和模糊掩码的位与运算现在,剩下要做的就是将这两个图像相加。右:原始图像/左:结果图像这是代码。import cv2import dlibimport faceBlendCommon as faceimport numpy as np# 加载图像im = cv2.imread("cv2/girl-no-makeup.jpg")# 检测人脸关键点PREDICTOR_PATH = r"C:Users elipe.cunhaDocuments envcv2week1-pytondatamodelsshape_predictor_68_face_landmarks.dat"faceDetector = dlib.get_frontal_face_detector()landmarkDetector = dlib.shape_predictor(PREDICTOR_PATH)landmarks = face.getLandmarks(faceDetector, landmarkDetector, im)# 为嘴唇制作一个掩码lipsPoints = landmarks[48:60]mask = np.zeros((im.shape[0], im.shape[1], 3), dtype=np.float32)cv2.fillConvexPoly(mask, np.int32(lipsPoints), (1.0, 1.0, 1.0))mask = 255*np.uint8(mask)# 应用闭合操作改善掩码kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,40))mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, 1)# 模糊掩码以获得自然效果mask = cv2.GaussianBlur(mask,(15,15),cv2.BORDER_DEFAULT)# 计算逆掩码inverseMask = cv2.bitwise_not(mask)# 将掩码转换为浮点以执行混合mask = mask.astype(float)/255inverseMask = inverseMask.astype(float)/255# 为嘴唇应用颜色贴图lips = cv2.applyColorMap(im, cv2.COLORMAP_INFERNO)# 将嘴唇和人脸转换为0-1范围lips = lips.astype(float)/255ladyFace = im.astype(float)/255# 用掩码调整嘴唇和脸justLips = cv2.multiply(mask, lips)justFace = cv2.multiply(inverseMask, ladyFace)# 加上脸和嘴唇result = justFace + justLips# 显示结果cv2.imshow("", result)cv2.waitKey(0)
  • [技术干货] 用Python和OpenCV为对象检测任务实现最流行、最高效的数据扩充
    数据扩充是一种增加数据集多样性的技术,无需收集更多真实数据,但仍有助于提高模型精度并防止模型过拟合。在本文中,你将学习使用Python和OpenCV为对象检测任务实现最流行、最高效的数据扩充过程。即将引入的一组数据扩充方法包括:1.随机裁剪2.Cutout3.颜色抖动4.增加噪音5.过滤首先,在继续之前,让我们导入几个库并准备一些必要的子例程。import osimport cv2import numpy as npimport randomdef file_lines_to_list(path):   '''          ### 在TXT文件里的行转换为列表 ###           path: 文件路径          '''           with open(path) as f:           content = f.readlines()           content = [(x.strip()).split() for x in content]           return contentdef get_file_name(path):          '''          ### 获取Filepath的文件名 ###          path: 文件路径          '''          basename = os.path.basename(path)          onlyname = os.path.splitext(basename)[0]          return onlynamedef write_anno_to_txt(boxes, filepath):         '''         ### 给TXT文件写注释 ###         boxes: format [[obj x1 y1 x2 y2],...]         filepath: 文件路径         '''         txt_file = open(filepath, "w")         for box in boxes:              print(box[0], int(box[1]), int(box[2]), int(box[3]), int(box[4]), file=txt_file)         txt_file.close()下面的图片是在这篇文章中使用的示例图片。随机裁剪随机裁剪随机选择一个区域并进行裁剪以生成新的数据样本,裁剪后的区域应具有与原始图像相同的宽高比,以保持对象的形状。从上图中,左侧图像表示具有边界框(红色)的原始图像,通过裁剪橙色框内的区域创建一个新样本作为右侧图像。在新示例的注释中,将删除与左侧图像中的橙色框不重叠的所有对象,并细化位于橙色框边界上的对象的坐标,使其适合新图像示例。原始图像的随机裁剪输出为新裁剪图像及其注释。CutoutTerrance DeVries和Graham W.Taylor在2017年的论文中介绍了Cutout,它是一种简单的正则化技术,用于在训练过程中随机屏蔽输入的方块区域,可用于提高卷积神经网络的鲁棒性和整体性能。这种方法不仅非常容易实现,而且还表明它可以与现有形式的数据扩充和其他正则化工具结合使用,以进一步提高模型性能。如本文所述,剪切用于提高图像识别(分类)的准确性,因此,如果我们将相同的方案部署到对象检测数据集中,可能会导致丢失对象的问题,尤其是小对象。在下图中,cutout区域(黑色区域)内的大量小对象被移除,这不符合数据扩充的精神。为了使这种方式适用于对象检测,我们可以进行简单的修改,而不是仅使用一个蒙版并将其放置在图像中的随机位置。当我们随机选择一半数量的对象并将剪切应用于这些对象区域时,效果会更好。增强图像如下图中的右图所示。剪切输出是新生成的图像,我们不移除对象或更改图像大小,则生成图像的注释与原始图像相同。def cutout(img, gt_boxes, amount=0.5):         '''         ### Cutout ###         img: 图像         gt_boxes: format [[obj x1 y1 x2 y2],...]         amount: 蒙版数量/对象数量         '''         out = img.copy()         ran_select = random.sample(gt_boxes, round(amount*len(gt_boxes)))         for box in ran_select:             x1 = int(box[1])             y1 = int(box[2])             x2 = int(box[3])             y2 = int(box[4])             mask_w = int((x2 - x1)*0.5)             mask_h = int((y2 - y1)*0.5)             mask_x1 = random.randint(x1, x2 - mask_w)             mask_y1 = random.randint(y1, y2 - mask_h)             mask_x2 = mask_x1 + mask_w             mask_y2 = mask_y1 + mask_h             cv2.rectangle(out, (mask_x1, mask_y1), (mask_x2, mask_y2), (0, 0, 0), thickness=-1)         return out颜色抖动ColorJitter是另一种简单的图像数据增强,我们可以随机改变图像的亮度、对比度和饱和度。我相信这个技术很容易被大多数读者理解。增加噪声在一般意义上,噪声被认为是图像中的一个意外因素,然而,几种类型的噪声(例如高斯噪声、椒盐噪声)可用于数据增强,在深度学习中添加噪声是一种非常简单和有益的数据增强方法。在下面的示例中,为了增强数据,将高斯噪声和椒盐噪声添加到原始图像中。对于那些无法识别高斯噪声和椒盐噪声之间差异的人,高斯噪声的值范围为0到255,具体取决于配置,因此,在RGB图像中,高斯噪声像素可以是任何颜色。相比之下,椒盐噪波像素只能有两个值0或255,分别对应于黑色(PEPER)或白色(salt)。滤波本文介绍的最后一个数据扩充过程是滤波。与添加噪声类似,滤波也简单且易于实现。实现中使用的三种类型的滤波包括模糊(平均)、高斯和中值。总结在这篇文章中,向大家介绍了一个关于为对象检测任务实现数据增强的教程。你们可以在这里找到完整实现。
  • [技术干货] 什么是 OpenCV?计算机视觉基本任务入门
    如果你有兴趣或计划做与图像或视频相关的事情,你绝对应该考虑使用。计算机视觉 (CV) 是 (AI) 的一个分支,它使计算机能够从图像、视频和其他视觉输入中提取有意义的信息,并采取必要的行动。例如自动驾驶汽车、自动交通管理、监控、基于图像的质量检查等等。什么是 OpenCV?OpenCV 是一个主要针对计算机视觉的库。它拥有你在使用计算机视觉 (CV) 时所需的所有工具。“Open”代表开源,“CV”代表计算机视觉。我会学到什么?本文包含使用 OpenCV 库开始使用计算机视觉所需的全部内容。你会在计算机视觉方面感到更加自信和高效。读取和显示图像首先让我们了解如何读取图像并显示它,这是CV的基础知识。读取图像:import numpy as npimport cv2 as cvimport matplotlib.pyplot as pltimg=cv2.imread('../input/images-for-computer-vision/tiger1.jpg')'img' 包含 numpy 数组形式的图像。让我们打印它的类型和形状print(type(img))print(img.shape)numpy 数组的形状为 (667, 1200, 3),其中,667 – 图像高度,1200 – 图像宽度,3 – 通道数,在这种情况下,有 RGB 通道,所以我们有 3 个通道。原始图像是 RGB 的形式,但 OpenCV 默认将图像读取为 BGR,因此我们必须在显示之前将其转换回RGB显示图像:# Converting image from BGR to RGB for displayingimg_convert=cv.cvtColor(img, cv.COLOR_BGR2RGB)plt.imshow(img_convert)在图像上绘图我们可以绘制线条、形状和文本图像。# Rectanglecolor=(240,150,240) # Color of the rectanglecv.rectangle(img, (100,100),(300,300),color,thickness=10, lineType=8) ## For filled rectangle, use thickness = -1## (100,100) are (x,y) coordinates for the top left point of the rectangle and (300, 300) are (x,y) coordinates for the bottom right point# Circlecolor=(150,260,50)cv.circle(img, (650,350),100, color,thickness=10) ## For filled circle, use thickness = -1## (250, 250) are (x,y) coordinates for the center of the circle and 100 is the radius# Textcolor=(50,200,100)font=cv.FONT_HERSHEY_SCRIPT_COMPLEXcv.putText(img, 'Save Tigers',(200,150), font, 5, color,thickness=5, lineType=20)# Converting BGR to RGBimg_convert=cv.cvtColor(img, cv.COLOR_BGR2RGB)plt.imshow(img_convert)混合图像我们还可以使用 OpenCV 混合两个或多个图像。图像只不过是数字,你可以对数字进行加、减、乘、除运算,从而得到图像。需要注意的一件事是图像的大小应该相同。# For plotting multiple images at oncedef myplot(images,titles):          fig, axs=plt.subplots(1,len(images),sharey=True)          fig.set_figwidth(15)          for img,ax,title in zip(images,axs,titles):               if img.shape[-1]==3:                   img=cv.cvtColor(img, cv.COLOR_BGR2RGB) # OpenCV reads images as BGR, so converting back them to RGB               else:                   img=cv.cvtColor(img, cv.COLOR_GRAY2BGR)               ax.imshow(img)               ax.set_title(title)img1 = cv.imread('../input/images-for-computer-vision/tiger1.jpg')img2 = cv.imread('../input/images-for-computer-vision/horse.jpg')# Resizing the img1img1_resize = cv.resize(img1, (img2.shape[1], img2.shape[0]))# Adding, Subtracting, Multiplying and Dividing Imagesimg_add = cv.add(img1_resize, img2)img_subtract = cv.subtract(img1_resize, img2)img_multiply = cv.multiply(img1_resize, img2)img_divide = cv.divide(img1_resize, img2)# Blending Imagesimg_blend = cv.addWeighted(img1_resize, 0.3, img2, 0.7, 0) ## 30% tiger and 70% horsemyplot([img1_resize, img2], ['Tiger','Horse'])myplot([img_add, img_subtract, img_multiply, img_divide, img_blend], ['Addition', 'Subtraction', 'Multiplication', Division', 'Blending'])乘法图像几乎为白色,分割图像为黑色,这是因为白色表示255,黑色表示0。当我们将图像的两个像素值相乘时,我们得到的数字更大,因此其颜色变为白色或接近白色,与分割图像相反。图像变换图像变换包括平移、旋转、缩放、裁剪和翻转图像。img=cv.imread('../input/images-for-computer-vision/tiger1.jpg')width, height, _=img.shape# TranslatingM_translate=np.float32([[1,0,200],[0,1,100]]) # 200=> Translation along x-axis and 100=>translation along y-axisimg_translate=cv.warpAffine(img,M_translate,(height,width))# Rotatingcenter=(width/2,height/2)M_rotate=cv.getRotationMatrix2D(center, angle=90, scale=1)img_rotate=cv.warpAffine(img,M_rotate,(width,height))# Scalingscale_percent = 50width = int(img.shape[1] * scale_percent / 100)height = int(img.shape[0] * scale_percent / 100)dim = (width, height)img_scale = cv.resize(img, dim, interpolation = cv.INTER_AREA)# Flippingimg_flip=cv.flip(img,1) # 0:Along horizontal axis, 1:Along verticle axis, -1: first along verticle then horizontal# ShearingsrcTri = np.array( [[0, 0], [img.shape[1] - 1, 0], [0, img.shape[0] - 1]] ).astype(np.float32)dstTri = np.array( [[0, img.shape[1]*0.33], [img.shape[1]*0.85, img.shape[0]*0.25], [img.shape[1]*0.15,img.shape[0]*0.7]] ).astype(np.float32)warp_mat = cv.getAffineTransform(srcTri, dstTri)img_warp = cv.warpAffine(img, warp_mat, (height, width))myplot([img, img_translate, img_rotate, img_scale, img_flip, img_warp],             ['Original Image', 'Translated Image', 'Rotated Image', 'Scaled Image', 'Flipped Image', 'Sheared Image'])图像预处理阈值处理:在阈值处理中,小于阈值的像素值变为 0(黑色),大于阈值的像素值变为 255(白色)。我将阈值设为 150,但你也可以选择任何其他数字。# For visualising the filtersimport plotly.graph_objects as gofrom plotly.subplots import make_subplotsdef plot_3d(img1, img2, titles):          fig = make_subplots(rows=1, cols=2,                  specs=[[{'is_3d': True}, {'is_3d': True}]],                         subplot_titles=[titles[0], titles[1]],                         )          x, y=np.mgrid[0:img1.shape[0], 0:img1.shape[1]]          fig.add_trace(go.Surface(x=x, y=y, z=img1[:,:,0]), row=1, col=1)          fig.add_trace(go.Surface(x=x, y=y, z=img2[:,:,0]), row=1, col=2)          fig.update_traces(contours_z=dict(show=True, usecolormap=True,                                         highlightcolor="limegreen", project_z=True))          fig.show()img=cv.imread('../input/images-for-computer-vision/simple_shapes.png')# Pixel value less than threshold becomes 0 and more than threshold becomes 255_,img_threshold=cv.threshold(img,150,255,cv.THRESH_BINARY)plot_3d(img, img_threshold, ['Original Image', 'Threshold Image=150'])应用阈值后,150 的值变为等于 255过滤: 图像过滤是通过改变像素的值来改变图像的外观。每种类型的过滤器都会根据相应的数学公式更改像素值。我不会在这里详细介绍数学,但我将通过在 3D 中可视化它们来展示每个过滤器的工作原理。limg=cv.imread('../input/images-for-computer-vision/simple_shapes.png')# Gaussian Filterksize=(11,11) # Both should be odd numbersimg_guassian=cv.GaussianBlur(img, ksize,0)plot_3d(img, img_guassian, ['Original Image','Guassian Image'])# Median Filterksize=11img_medianblur=cv.medianBlur(img,ksize)plot_3d(img, img_medianblur, ['Original Image','Median blur'])# Bilateral Filterimg_bilateralblur=cv.bilateralFilter(img,d=5, sigmaColor=50, sigmaSpace=5)myplot([img, img_bilateralblur],['Original Image', 'Bilateral blur Image'])plot_3d(img, img_bilateralblur, ['Original Image','Bilateral blur'])高斯滤波器:通过去除细节和噪声来模糊图像。中值滤波器:非线性过程可用于减少脉冲噪声或椒盐噪声双边滤波器:边缘保留和降噪平滑。简单来说,过滤器有助于减少或去除亮度或颜色随机变化的噪声,这称为平滑。特征检测特征检测是一种通过计算图像信息的抽象,在每个图像点上做出局部决策的方法。例如,对于一张脸的图像,特征是眼睛、鼻子、嘴唇、耳朵等,我们尝试识别这些特征。让我们首先尝试识别图像的边缘。边缘检测img=cv.imread('../input/images-for-computer-vision/simple_shapes.png')img_canny1=cv.Canny(img,50, 200)# Smoothing the img before feeding it to cannyfilter_img=cv.GaussianBlur(img, (7,7), 0)img_canny2=cv.Canny(filter_img,50, 200)myplot([img, img_canny1, img_canny2],             ['Original Image', 'Canny Edge Detector(Without Smoothing)', 'Canny Edge Detector(With Smoothing)'])这里我们使用 Canny 边缘检测器,它是一种边缘检测算子,它使用多阶段算法来检测图像中的各种边缘。它由 John F. Canny 于 1986 年开发。我不会详细介绍 Canny 的工作原理,但这里的关键点是它用于提取边缘。在使用 Canny 边缘检测方法检测边缘之前,我们平滑图像以去除噪声。正如你从图像中看到的,平滑后我们得到清晰的边缘。轮廓img=cv.imread('../input/images-for-computer-vision/simple_shapes.png')img_copy=img.copy()img_gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)_,img_binary=cv.threshold(img_gray,50,200,cv.THRESH_BINARY)#Edroing and Dilating for smooth contoursimg_binary_erode=cv.erode(img_binary,(10,10), iterations=5)img_binary_dilate=cv.dilate(img_binary,(10,10), iterations=5)contours,hierarchy=cv.findContours(img_binary,cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)cv.drawContours(img, contours,-1,(0,0,255),3) # Draws the contours on the original image just like draw functionmyplot([img_copy, img], ['Original Image', 'Contours in the Image'])侵蚀,使用用于探测和降低包含在图像中的形状的结构元素的侵蚀操作。膨胀:将像素添加到图像中对象的边界,与侵蚀相反Hullsimg=cv.imread('../input/images-for-computer-vision/simple_shapes.png',0)_,threshold=cv.threshold(img,50,255,cv.THRESH_BINARY)contours,hierarchy=cv.findContours(threshold,cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)hulls=[cv.convexHull(c) for c in contours]img_hull=cv.drawContours(img, hulls,-1,(0,0,255),2) #Draws the contours on the original image just like draw functionplt.imshow(img)总结我们看到了如何读取和显示图像、在图像上绘制形状、文本、混合两个图像、旋转、缩放、平移等变换图像,使用高斯模糊、中值模糊、双边模糊过滤图像,以及检测使用 Canny 边缘检测和在图像中查找轮廓的特征。
  • [技术干货] 如何使用OpenCV和DLIB在图像上操作人脸?
    这是一个关于如何使用OpenCV和DLIB在图像上应用虚拟唇膏的快速教程。同样的原理也可以推广到其他面部特征,比如某人的眼睛、鼻子、下巴……。为了获得上图所示的结果,我们需要执行以下一系列步骤:检测面部标志使用由嘴标志组成的凸多边形创建掩码使用形态学操作增强掩码,并使其模糊,以获得更好的混合效果隔离嘴唇和脸部将颜色变换应用于嘴唇把嘴唇和脸放在一起首先要做的是检测人脸的面部标志。库Dlib提供了一种方便的方法来实现这一点;但是,请记住,被摄对象的面部需要面对摄影机。如果头部姿势不正确,检测结果将不好。在这个例子中,我们只对嘴唇的点感兴趣。下图显示了Dlib返回的面部标志点的索引。如你所见,我们对48点到60点(嘴唇的外部“轮廓”)感兴趣。利用这些点,我们可以制作一个掩码,让我们在不影响面部整体外观的情况下处理嘴唇的颜色。但是,等一下。在开始操作这些颜色之前,我们需要改进掩码。在这个例子中,一个带有4x4矩形内核的形态学闭合操作就足够了。注意下面的图片,这个步骤填补了由cv2生成的原始多边形右上角的一个空白。右:使用唇部创建的凸多边形/左:关闭操作后的多边形为了获得自然的效果,我们还需要模糊掩码。模糊掩码将产生更好的混合效果。我们将cv2.GaussianBlur应用于掩码。最后,我们反转掩码(我们需要两个,一个用于嘴唇,一个用于面部)。右:模糊掩码/左:模糊反向掩码我们将应用这些掩码,方法是将它们从0–255(uint8)转换为0–1(float)范围,然后将它们与图像相乘。右下方的图像是原始图像乘以反转掩码。左侧的图像是原始图像上的颜色变换乘以掩码的结果。颜色变换由cv2.applyColorMap(im, cv2.COLORMAP_INFERNO)给出。右:原始图像和反向模糊掩码的位与运算/左:颜色变换图像和模糊掩码的位与运算现在,剩下要做的就是将这两个图像相加。右:原始图像/左:结果图像这是代码。import cv2import dlibimport faceBlendCommon as faceimport numpy as np# 加载图像im = cv2.imread("cv2/girl-no-makeup.jpg")# 检测人脸关键点PREDICTOR_PATH = r"C:Users elipe.cunhaDocuments envcv2week1-pytondatamodelsshape_predictor_68_face_landmarks.dat"faceDetector = dlib.get_frontal_face_detector()landmarkDetector = dlib.shape_predictor(PREDICTOR_PATH)landmarks = face.getLandmarks(faceDetector, landmarkDetector, im)# 为嘴唇制作一个掩码lipsPoints = landmarks[48:60]mask = np.zeros((im.shape[0], im.shape[1], 3), dtype=np.float32)cv2.fillConvexPoly(mask, np.int32(lipsPoints), (1.0, 1.0, 1.0))mask = 255*np.uint8(mask)# 应用闭合操作改善掩码kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,40))mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, 1)# 模糊掩码以获得自然效果mask = cv2.GaussianBlur(mask,(15,15),cv2.BORDER_DEFAULT)# 计算逆掩码inverseMask = cv2.bitwise_not(mask)# 将掩码转换为浮点以执行混合mask = mask.astype(float)/255inverseMask = inverseMask.astype(float)/255# 为嘴唇应用颜色贴图lips = cv2.applyColorMap(im, cv2.COLORMAP_INFERNO)# 将嘴唇和人脸转换为0-1范围lips = lips.astype(float)/255ladyFace = im.astype(float)/255# 用掩码调整嘴唇和脸justLips = cv2.multiply(mask, lips)justFace = cv2.multiply(inverseMask, ladyFace)# 加上脸和嘴唇result = justFace + justLips# 显示结果cv2.imshow("", result)cv2.waitKey(0)
  • [技术干货] 使用OpenCV,构建文档扫描仪
    本文将使用 OpenCV,创建一个简单的文档扫描仪,就像常用的摄像头扫描仪应用程序一样。这个想法很简单,因为我们认为文档是四边形,我们获取边缘的位置并使用它来抓取文档本身,而忽略无用的图像背景。简单的管道:加载图像>>检测边缘和抓取位置>>使用图像上的位置导入包首先,我们导入处理图像可能需要的包。threshold_local 函数对你来说可能看起来很新,但这段代码其实没有什么特别之处。该函数来自 scikit 图像包。# import packagesfrom skimage.filters import threshold_localimport numpy as npimport cv2import imutils加载图像。在这里,我们加载图像并保留一份副本。在这里,原始的副本对于获得清晰且未经篡改的图像扫描非常重要。为了处理图像,我调整到一个合理的比例,接下来我对图像进行灰度化以减少颜色并使其模糊(即有助于从图像背景中去除高频噪声),这些都是为了找到文件的边缘。#load in the imageimage = cv2.imread("images/questions.jpg")orig  = image.copy()#Resize the image.height = image.shape[0]width = image.shape[1]ratio = 0.2width = int(ratio * width)height = int(ratio * height)image = cv2.resize(image,(width, height))#find edges in the image.gray_scaled = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#blurr the imagegray_scaled = cv2.GaussianBlur(gray_scaled,(5,5),0)#Edge detectionedged = cv2.Canny(gray_scaled,50, 200)cv2.imshow("Image", image)cv2.waitKey(0)cv2.imshow("Edges detected", edged)cv2.waitKey(0)找到轮廓。使用 cv2.findcontours() 找到轮廓。接下来,我们使用 imutils 库抓取轮廓,最后,我们根据最大轮廓区域,对抓取的轮廓进行排序。在这种情况下,我保留了最大的 5 个# find contours in the edged image. keep only the largest contours.contours = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)# grab contourscontours = imutils.grab_contours(contours)# select contours based on size.contours = sorted(contours, key=cv2.contourArea, reverse = True)[:5]对轮廓进行进一步处理。首先,我们遍历轮廓并找到周长,这是将周长近似为点所必需的。完成此操作后,我们最终搜索恰好具有 4 个点的轮廓,这很可能是近似矩形形状的纸张。完成后,我们获取这些点的坐标,然后将它们初始化为纸张轮廓。# loop over the contours.for contour in contours:   perimeter = cv2.arcLength(contour, True)   # approximate your contour   approximation = cv2.approxPolyDP(contour, 0.02*perimeter, True)      # if our contour has 4 points, then surely, it should be the paper.   if len(approximation) == 4:       paper_outline = approximation       break有了坐标,下一步就是画轮廓,很简单。# Draw the found contour.cv2.drawContours(image,[paper_outline],-1,(225,0,0),2)cv2.imshow("Found outline", image)cv2.waitKey(0)你心中的问题是,我们完成了吗?好吧,你可能会说是的,因为你在图像周围设置了很好的轮廓。答案是否定的,为了获得最佳扫描形式的图像,我们需要 90 度的图像视图,尤其是在倾斜的情况下。为此,我们将创建一个函数来处理此任务。管道:排列点>>标记点>>从真实图像中挑选点arrange_points 函数。这样做的方法非常简单,归功于 Adrian Rosebrock(博士)。这个函数背后的直觉是我们获取文档四个边缘的坐标,并将其安排到我们认为它应该在的位置,我花了一些时间给出描述的图形表示。点坐标的和1)从上图中我们可以看出,点坐标(X,Y)的和最大的是在右上角。2)最小的点总和是左下点。点坐标的差3)点坐标的差的最大值是左上角4)点坐标的差的最小值是左下角。代码。该函数接受参数points,接下来,我初始化一个 NumPy 数组来表示矩形,该数组是一个 4 x 2 矩阵,因为我们有 4 个点和 2 个坐标(X,Y)。最后,如上所述,我在矩形的点中注册(点的和以及点的差)。最后,我正确地返回了 Rectangle 的坐标。def arrange_points(points):   # initialize a list of co-ordinates that will be ordered   # first entry is top-left point, second entry is top-right   # third entry is bottom-right, forth/last point is the bottom left point.   rectangle = np.zeros((4,2), dtype = "float32")      # bottom left point should be the smallest sum   # the top-right point will have the largest sum of point.   sum_points= points.sum(axis =1)   rectangle[0] = points[np.argmin(sum_points)]   rectangle[2] = points[np.argmax(sum_points)]         #bottom right will have the smallest difference   #top left will have the largest difference.   diff_points = np.diff(points, axis=1)   rectangle[1] = points[np.argmin(diff_points)]   rectangle[3] = points[np.argmax(diff_points)]         # return order of co-ordinates.   return rectangle设置四个点。这个功能很简单,这里的想法当然是拉直纸张,只提取需要的区域。在这里,输入是 1) 图像本身和点或坐标。首先,我们使用我们创建的第一个函数“arrange_points”来排列函数的点。接下来,我相应地分配了点,因为我之前已经安排了点并且也很好地命名了它们。计算。对于计算,只需两点之间的距离即可找到每边的长度。有了这个,我们能够在对的位置上防止错误地调整图像。顾名思义,目的地是图像的新视图。其中 [0,0] 表示左上角。接下来,[Max-width - 1,0] 表示右上角,我们还有 [maxwidth -1, maxheight-1] 表示底部右上角,最后是左下角 [0, max-height -1]。转换矩阵动作完成,工作结束,我们需要完成的是使用 cv2.getPerspectiveTransform() 的变换矩阵,它接受点的矩形和目的地。现在我们有了矩阵,我们使用 cv2.warpPerspective() 应用它,它获取你提供给函数的图像、变换矩阵,最后是建议扫描的(宽度和长度)。全部完成,返回转换后的图像# set four points.def set_four_points(image, points):   # obtain order of points and unpack.   rectangle = arrange_points(points)   (top_left,top_right,bottom_right,bottom_left) = rectangle   # let's compute width of the rectangle.   # using formular for distance between two points   left_height = np.sqrt(((top_left[0]-bottom_left[0])**2) + ((top_left[1]-bottom_left[1])**2))   right_height = np.sqrt(((top_right[0]-bottom_right[0])**2) + ((top_right[1]-bottom_right[1])**2))   top_width = np.sqrt(((top_right[0]-top_left[0])**2) + ((top_right[1]-top_left[1])**2))   bottom_width = np.sqrt(((bottom_right[0]-bottom_left[0])**2) + ((bottom_right[1]-bottom_left[1])**2))      maxheight = max(int(left_height), int(right_height))   maxwidth  = max(int(top_width), int(bottom_width))      destination = np.array([       [0,0],       [maxwidth -1,0],       [maxwidth -1, maxheight-1],       [0, maxheight - 1]], dtype = "float32")                matrix = cv2.getPerspectiveTransform(rectangle, destination)      warped = cv2.warpPerspective(image, matrix, (maxwidth,maxheight))      return warped应用函数我们已经创建了函数,因此我们将其应用于最初保存的原始图像。第二个输入是论文的大纲。我通过删除我在开始时所做的比例缩放,将纸张轮廓重新调整回原来的大小。要获得图像的黑白感觉,需要使用 Threshold local,但当然,如果你想要对图像进行彩色扫描,则根本不需要它。最后,我调整大小并显示。warped = set_four_points(orig, paper_outline.reshape(4,2)*(1/ratio))#warped = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)#threshold = threshold_local(warped, 11, offset=10, method="gaussian")#warped = (warped > threshold).astype("uint8") * 255#show the original and scanned imagesprint("Image Reset in progress")cv2.imshow("Original", cv2.resize(orig,(width, height)))cv2.imshow("Scanned",cv2.resize(warped,(width, height)))cv2.waitKey(0)干得好!!,你刚刚创建了自己的扫描仪应用程序。       原文标题 : 构建文档扫描仪
  • [技术干货] Python中OpenCV的基础知识
    从安装到基本图像处理OpenCV 是一个流行的开源库,可用于不同的编程语言,例如 Python、C++ 和 JavaScript。它提供了一套丰富的工具来处理和分析图像和视频,让你可以从调整单张图片的大小到构建复杂的对象识别应用程序。Python 编程语言除了被广泛用作大多数图像处理和计算机视觉应用程序的标准外,还允许以非常直接的方式将 OpenCV 安装在你的计算机中。在本教程中,我将向你展示使用 OpenCV 安装、设置和对图像执行一些基本操作所需的步骤,重点介绍有关该库背后概念的重要基础知识。值得一提的是,这些步骤是在基于 Linux 的操作系统中使用Python3执行的。因此,如果你使用不同的配置,则可能需要进行细微的更改。设置虚拟环境使用 Python 时,通常建议在虚拟环境中运行你的应用程序。这样做,你可以只安装运行应用程序所需的包,使其独立于系统的其余部分。如果你的计算机上仍然没有安装虚拟环境工具,我建议你安装以下工具。python3 -m pip install virtualenv安装后,你可以使用此工具创建新的虚拟环境。为此,导航到你想要的目录并运行以下命令。请注意,我为我的环境选择了名称 my_venv,但你可以选择任何你想要的名称。python3 -m venv my_venv最后,你只需要激活你的虚拟环境,以便你在此终端中运行的任何内容都将在其中完成。source my_venv/bin/activate安装 OpenCV首先更新你的包管理器并为 Python3 安装 OpenCV。sudo apt updatesudo apt install python3-opencv然后,使用 pip 在你的虚拟环境中安装 OpenCV。pip install opencv-python打开图像使用你最喜欢的 IDE,创建一个扩展名为 .py 的新文件,然后从导入 OpenCV 类开始import cv2我们在这里做的第一件事是使用 imread() 方法加载图像并使用 imshow() 方法打开它。请将下面的路径替换为你的图片所在的路径。image = cv2.imread("images/messi.jpg")cv2.imshow("Original image", image)原始图像关于 OpenCV 如何解释图像的第一个有趣的点是,imread()返回一个n 维数组对象。对于 RGB 图像,例如本例中使用的图像,此数组具有以下形状:[宽×高×通道数]你可以通过打印图像形状来确认这一点。print("Original image shape:", image.shape)更改图像色彩空间颜色空间是用于描述图像的光谱上的一系列颜色。尽管有多种颜色空间可用,但最常见的是 RGB 和灰度。OpenCV 包含一种特殊的颜色空间转换方法。为了将图像从 RGB 转换为灰度,你需要应用 cvtColor()方法。image_grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)cv2.imshow(“Grayscale image”, image_grayscale)灰度图像重要的是要注意,现在你的图像不再包含三个维度。那是因为对应于通道的第三维在灰度色彩空间中没有使用。print("Grayscale image shape:", image_grayscale.shape)编辑图像通道返回到包含三个颜色通道的原始图像,你现在可以操纵每个通道的强度值,以抑制或突出显示特定通道。与通常假设的相反,RGB 通道的访问顺序与首字母缩写词中的顺序不同。在 OpenCV 中,通道实际上以 BGR 格式提供:0 = B(蓝色)1 = G(绿色)2 = R(红色)在下面的示例中,我检索前两个通道中的所有像素并将它们设为零,这样绿色和蓝色通道将不会对生成的图像产生任何影响,因此图像将呈现完全红色调。image_red = image.copy()image_red[:, :, :2] = 0 cv2.imshow("Red image", image_red)具有空蓝色和绿色通道的图像打印红色图像形状时,请注意仍然存在第三维,否则生成的图像将被描述为灰度print("Red image shape:", image_red.shape)旋转图像除了颜色之外,还可以对图像形状进行操作,例如大小和方向。你可以从获取图像尺寸开始,就像 NumPy 对象一样。width, height, _ = image.shape然后可以通过取其宽度和高度的一半来计算图像的中心点。center = (width//2, height//2)为了旋转图像,你首先必须创建一个旋转矩阵,分别将中心点、所需的旋转度数和图像比例作为参数传递。使用不同于 1 的比例会改变图像大小。rotation_matrix = cv2.getRotationMatrix2D(center, 45, 1.0) 旋转矩阵对象本身不足以做我们想要的。它作为参数传递给 warpAffine() 方法,这是实际执行旋转的方法。image_rotated = cv2.warpAffine(image, rotation_matrix, (width, height))cv2.imshow(“Rotated image”, image_rotated)旋转图像调整图像大小你可以使用之前获得的高度和宽度值来定义图像的新尺寸。在下面的示例中,我将它们设置为将图像缩小到其原始大小的三分之一。new_size = (width//3, height//3)负责调整图像大小的方法是resize(),它分别需要原始图像对象、所需的新大小和插值方法作为参数。image_resized = cv2.resize(image, new_size, interpolation=cv2.INTER_LINEAR)cv2.imshow(“Resized image”, image_resized)调整大小的图像然后,你可以检查调整大小的图像的尺寸。print(“Resized image shape:”, image_resized.shape)将绘图插入图像在某些应用程序中,可能需要向图像添加标记。OpenCV 类提供了多种在其上绘制线条和形状的方法。如下添加一行。这里的参数是原始图像、初始位置、最终位置、线条颜色 RGB 代码和线条宽度。请注意,实际上使用的是原始图像的副本,因为绘图方法会影响原始图像。image_line = cv2.line(image.copy(), (0, 0), (height//2, width//2), (0, 255, 255), 10)cv2.imshow(“Image with line”, image_line)带线条的图像同样,在图像中绘制矩形也有特定的方法。在这种情况下,第二个和第三个参数是矩形相对顶点的位置(左上角和右下角)。image_rectangle = cv2.rectangle(image.copy(), (500, 150), (900, 550), (0, 255, 255), 5)cv2.imshow(“Image with rectangle”, image_rectangle)带有矩形的图像你还可以通过将圆的中心位置和半径分别指定为第二个和第三个参数来绘制一个圆。image_circle = cv2.circle(image.copy(), (300, 300), 200, (0, 255, 255), 5)cv2.imshow(“Image with circle”, image_circle)带圆的图像       原文标题 : Python中OpenCV的基础知识
总条数:305 到第
上滑加载中