-
OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 [1] 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。opencv是一个开源的计算机视觉开发包,这已是众所周知的了,而且越来越多的人开始研究它了。但opencv的使用者还是以高校居多,企业用得比较少,而企业使用opencv也往往是借鉴它的一些算法。计算机视觉市场巨大而且持续增长,且这方面没有标准API,如今的计算机视觉软件大概有以下三种:1、研究代码(慢,不稳定,独立并与其他库不兼容)2、耗费很高的商业化工具(比如Halcon, MATLAB+Simulink)3、依赖硬件的一些特别的解决方案(比如视频监控,制造控制系统,医疗设备)这是如今的现状,而标准的API将简化计算机视觉程序和解决方案的开发,OpenCV致力于成为这样的标准API。OpenCV致力于真实世界的实时应用,通过优化的C代码的编写对其执行速度带来了可观的提升,并且可以通过购买Intel的IPP高性能多媒体函数库(Integrated Performance Primitives)得到更快的处理速度。OpenCV与其它视觉函数库性能对比(来源百度百科) 作为开源软件,opencv的优势就是在于它有400多个免费的图像处理函数,而且涉及的面很广,从图像处理到模式识别、从静态图像到运动视频、从二维平面到相机的三维标定以及三维重建,覆盖了机器视觉的大多应用领域。它的许多算法,也是做了很好的优化的,比绝大多数教科书(当然指国内的教科书)算法优化得好。而国内的教科书,很多时候连一个算法也没讲明白过,更不用说到优化了。所以,用好opencv的开发包,就是一个不错的教材。
-
- 使用MindX框架,通过SendProtobuf将原始YUV/RGB图像发送给Pipeline,通过mxpi_imageresize插件缩放到模型输入尺寸后进行检测流程。目前使用Opencv模拟输入原始YUV/RGB图像,但无论是YUV还是RGB都不能正常跑通或识别正确。 - 输出的图片如下所示,存在花屏和错位,不知道是Opencv转MxstDataInput存在问题,还是resize没用使用正确。 
-
OpenCV 中国镜像仓:https://gitcode.net/opencvOpenCV是一个基于Apache 2.0 许可证(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、macOS、Android和iOS操作系统上。为了解决克隆 OpenCV 源码以及构建过程的下载问题,OpenCV 中国团队联系了国内一家提供代码托管服务的网站 GitCode.net,双方对 OpenCV 中国镜像的想法一拍即合,为广大 OpenCV 的开发者提供便利。这样下载就不会慢了~
-
已连接上网,但是还是Unable to locate package libopencv-dev
-
本文转自:opcv学堂本文来自光头哥哥的博客【Measuring distance between objects in an image with OpenCV】,仅做学习分享。原文链接:https://www.pyimagesearch.com/2016/04/04/measuring-distance-between-objects-in-an-image-with-opencv/已经完成了测量物体大小的任务,今天进行最后一部分:计算图片中物体之间的距离。上篇我们讨论了如何使用参考对象来测量图像中对象的大小。这个参考对象应该有两个重要的特征,包括:• 我们知道这个物体的尺寸(以英寸、毫米等表示)。• 它很容易在我们的图像中被识别出来(根据位置或外观)。给定这样一个参考对象,我们可以使用它来计算图像中对象的大小。今天,我们将结合本系列前两篇来计算对象之间的距离。计算物体之间的距离与计算图像中物体的大小算法思路非常相似——都是从参考对象开始的。我们将使用0.25美分作为我们的参考对象,它的宽度为0.955英寸。并且我们还将0.25美分总是放在图片最左侧使其容易识别。这样它就满足了我们上面提到的参考对象的两个特征。我们的目标是找到0.25美分,然后利用0.25美分的尺寸来测量0.25美分硬币与所有其他物体之间的距离。定义参考对象并计算距离打开一个新文件,将其命名为distance_between.py,插入以下代码: # import the necessary packages from scipy.spatial import distance as dist from imutils import perspective from imutils import contours import numpy as np import argparse import imutils import cv2 def midpoint(ptA, ptB): return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5) # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to the input image") ap.add_argument("-w", "--width", type=float, required=True, help="width of the left-most object in the image (in inches)") args = vars(ap.parse_args())# import the necessary packages我们这里的代码与上周的代码几乎相同。我们从在第2-8行上导入所需的Python包开始。 第12-17行解析命令行参数。这里我们需要两个参数:——image,它是包含我们想要测量的对象的输入图像的路径,以及——width,为我们参考对象的宽度(单位为英寸)。接下来,我们需要对图像进行预处理:# load the image, convert it to grayscale, and blur it slightly image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray, (7, 7), 0) # perform edge detection, then perform a dilation + erosion to # close gaps in between object edges edged = cv2.Canny(gray, 50, 100) edged = cv2.dilate(edged, None, iterations=1) edged = cv2.erode(edged, None, iterations=1) # find contours in the edge map cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) # sort the contours from left-to-right and, then initialize the # distance colors and reference object (cnts, _) = contours.sort_contours(cnts) colors = ((0, 0, 255), (240, 0, 159), (0, 165, 255), (255, 255, 0), (255, 0, 255)) refObj = None第2-4行从磁盘加载图像,将其转换为灰度图,然后使用7 x 7内核的高斯滤波器对其进行模糊降噪。当我们的图像被模糊后,我们应用Canny边缘检测器来检测图像中的边缘,然后进行膨胀+腐蚀来缩小边缘图中的缝隙(第7-9行)。调用cv2.findContours检测边缘图中对象的轮廓(第11-13行),而第16行从左到右对轮廓进行排序。由于我们知道0.25美分(即参考对象)将始终是图像中最左边,因此从左到右对轮廓进行排序可以确保与参考对象对应的轮廓始终是cnts列表中的第一个。然后,我们初始化用于绘制距离的colors列表以及refObj变量,该变量将存储参考对象的边界框、质心和pixels-per-metric值(看上一篇就明白pixels-per-metric的具体定义,其实就是参考对象的实际大小(单位英寸)与图片中的宽度(单位为像素)的比值)。# loop over the contours individually for c in cnts: # if the contour is not sufficiently large, ignore it if cv2.contourArea(c) < 100: continue # compute the rotated bounding box of the contour box = cv2.minAreaRect(c) box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box) box = np.array(box, dtype="int") # order the points in the contour such that they appear # in top-left, top-right, bottom-right, and bottom-left # order, then draw the outline of the rotated bounding # box box = perspective.order_points(box) # compute the center of the bounding box cX = np.average(box[:, 0]) cY = np.average(box[:, 1])xxxxxxxxxx # loop over the contours individually# loop over the contours individuallyfor c in cnts: # if the contour is not sufficiently large, ignore itif cv2.contourArea(c) < 100:continue # compute the rotated bounding box of the contourbox = cv2.minAreaRect(c)box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)box = np.array(box, dtype="int") # order the points in the contour such that they appear # in top-left, top-right, bottom-right, and bottom-left # order, then draw the outline of the rotated bounding # boxbox = perspective.order_points(box) # compute the center of the bounding boxcX = np.average(box[:, 0])cY = np.average(box[:, 1])在第2行,我们开始对cnts列表中的每个轮廓进行循环。如果轮廓比较小(第4和5行),我们认为是噪声并忽略它。 然后,第7-9行计算当前对象的最小旋转包围框。第14行上调用order_points函数(此系列第一篇定义的函数)来对矩形框四个顶点以左上角、右上角、右下角和左下角的顺序排列,我们将看到,在计算物体之间的距离时,这一点非常重要。第16行和第17行通过取边界框在x和y方向上的平均值来计算旋转后的边界框的中心(x, y)坐标。下一步是校准我们的refObj:# if this is the first contour we are examining (i.e., # the left-most contour), we presume this is the # reference object if refObj is None: # unpack the ordered bounding box, then compute the # midpoint between the top-left and top-right points, # followed by the midpoint between the top-right and # bottom-right (tl, tr, br, bl) = box (tlblX, tlblY) = midpoint(tl, bl) (trbrX, trbrY) = midpoint(tr, br) # compute the Euclidean distance between the midpoints, # then construct the reference object D = dist.euclidean((tlblX, tlblY), (trbrX, trbrY)) refObj = (box, (cX, cY), D / args["width"]) continue如果refObj为None(第4行),则需要对其进行初始化。 我们首先获取(排序后的)最小旋转边界框坐标,并分别计算四个顶点之间的中点(第10-15行)。然后计算中点之间的欧氏距离,给出我们的“像素/尺寸”比例,来确定一英寸为多少像素宽度。最后,我们将refObj实例化为一个3元组,包括:• 物体对象的最小旋转矩形对象box• 参考对象的质心。• 像素/宽度比例,我们将用其来结合物体之间的像素距离来确定物体之间的实际距离。下一个代码块负责绘制参考对象和当前检查对象的轮廓,然后定义变量refCoords和objCoords,这样(1)最小包围矩阵坐标和(2)质心的(x, y)坐标都包含在同一个数组中:# draw the contours on the image orig = image.copy() cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2) cv2.drawContours(orig, [refObj[0].astype("int")], -1, (0, 255, 0), 2) # stack the reference coordinates and the object coordinates # to include the object center refCoords = np.vstack([refObj[0], refObj[1]]) objCoords = np.vstack([box, (cX, cY)])现在我们可以开始计算图像中各个物体的质心和质心之间的距离了: # loop over the original points for ((xA, yA), (xB, yB), color) in zip(refCoords, objCoords, colors): # draw circles corresponding to the current points and # connect them with a line cv2.circle(orig, (int(xA), int(yA)), 5, color, -1) cv2.circle(orig, (int(xB), int(yB)), 5, color, -1) cv2.line(orig, (int(xA), int(yA)), (int(xB), int(yB)), color, 2) # compute the Euclidean distance between the coordinates, # and then convert the distance in pixels to distance in # units D = dist.euclidean((xA, yA), (xB, yB)) / refObj[2] (mX, mY) = midpoint((xA, yA), (xB, yB)) cv2.putText(orig, "{:.1f}in".format(D), (int(mX), int(mY - 10)), cv2.FONT_HERSHEY_SIMPLEX, 0.55, color, 2) # show the output image cv2.imshow("Image", orig) cv2.waitKey(0)在第2行,我们开始对图片中物体对象的顶点(x, y)坐标进行循环。 然后我们画一个圆表示我们正在计算距离的当前点坐标,并画一条线连接这些点(第5-7条线)。然后,第12行计算参考位置和对象位置之间的欧式距离,然后除以“像素/度量”,得到两个对象之间的实际距离(以英寸为单位)。然后在图像上标识出计算的距离(第13-15行)。距离测量结果下面是一个GIF动画,演示了我们的程序运行效果: 在每种情况下,我们的脚本都匹配左上(红色)、右上(紫色)、右下(橙色)、左下(蓝绿色)和质心(粉色)坐标,然后计算参考对象和当前对象之间的距离(以英寸为单位)。注意图像中的两个0.25美分完全平行,这意味着所有五个顶点之间的距离均为6.1英寸。下面是第二个例子,这次计算的是参考对象和药丸之间的距离: 这个例子可以作为药片分类机器人的输入,自动获取一组药片,并根据它们的大小和与药片容器的距离来组织它们。 最后一个例子计算了我们的参考对象(一张3.5英寸x 2英寸的名片)和一组7英寸的黑胶唱片和信封之间的距离:
-
计算机视觉是最令人兴奋的领域之一,其应用范围非常广泛。从医学成像到创建最有趣的面部滤镜等各个领域都充分见证了计算机视觉技术的强大。在本文中,我们将尝试创建一个人造眼线笔来模仿Snapchat或Instagram滤波器,为视频中的美女添加上美丽的眼线。最终的结果可以通过下面的动图观察到。本文介绍的内容适合想要通过计算机视觉来实现一个具有一定展示性功能的计算机视觉初学者。因此,在本文重我们会尽量简化说明,如果您对完整的程序感兴趣,可以在Github上找到完整的代码。Github的链接在本文的文末给出。 在实现本文功能之前,我们需要设置一个新的虚拟环境并安装所有必需的依赖项。这个过程比较简单,我们也在Github里面给出了如何配置环境的具体过程。在本项目中,我们需要使用的工具有OpenCV,NumPy,imutils,SciPy和Dlib。有些小伙伴可能对这些工具和库比较陌生,接下来我们简单介绍一下每个模块的作用。• OpenCV:用于图像处理的最受欢迎的模块之一。我们将使用OpenCV读取,写入和绘制图像。• NumPy:在处理OpenCV项目时经常使用NumPy。图像本质上是一个像素数组,OpenCV使用以NumPy数组形式存储的这些数组,并对图像执行操作。• Imutils:Imutils附带了自定义功能,使我们的计算机视觉工作变得更加轻松。在这里,我们将使用它来将dlib对象转换为非常灵活且广泛接受的numpy数组。• Scipy:顾名思义,SciPy用于python上的科学计算。我们将使用它来创建插值(如果现在没有意义,可以的)。• Dlib:Dlib是一个包含各种ML算法的C ++库。我们将使用dlib提取面部界标点。项目简要介绍该程序首先从每个面孔中提取68个界标点。在这68个点中,点37–42属于左眼,点43–48属于右眼,具体形式如下图所示。因为我们的目标是给面部添加眼线,所以我们只对37-48点感兴趣,因此我们提取了这些点。我们将对这些提取的点进行插值。插值意味着我们尝试在两个给定点之间插入点。我们可以使用的插值方式如下图所示。眼线算法的流程图如下所示接下来,我们将进一步详细描述该算法。如果小伙伴只对运行代码感兴趣,可以跳至最后一部分。算法介绍我们首先需要提取脸部周围边界框的坐标。OpenCV将图像转换为NumPy数组。numpy.array(即图像的矩阵表示形式)存储在名为的变量中frame。我们使用一个名为face_detector()的函数,该函数返回围绕框架中所有脸部的包围框的坐标。这些边界框坐标存储在一个名为bounding_boxes的变量中。遍历循环bounding_boxes以将眼线应用于帧中检测到的每个脸部。face_landmark_points存储68个坐标点。eye_landmark_points是从getEyeLandmarkPts()函数中得到。getEyeLandmarkPts()函数使用68个坐标点作为输入并返回具有左上眼睑的坐标4个矩阵,左上眼线(L_eye_top),左下眼线(L_eye_bottom)和相同的右眼(R_eye_top & R_eye_bottom)。这可以通过简单的NumPy索引完成的。我们将端点(pt号37、40、43和46。请参见68个界标点图)向外移动5px,以使外观更逼真。现在,我们需要对这些点进行插值以获得平滑的曲线,进而可以画出眼线。我们需要对每个曲线进行不同的处理(即L_eye_top,L_eye_bottom,R_eye_top,R_eye_bottom)。因此,我们为每个曲线使用单独的变量名称。interpolateCoordinates()用于在每条曲线上生成插值。重复使用该函数,为每个曲线生成插值坐标。这个函数为每个曲线返回一个插值点数组。drawEyeLiner()函数将生成的插值点作为参数,并在两个连续点之间画一条线。在两个循环中为每个曲线完成此操作,一个循环用于左眼,另一个循环用于右眼。 调用项目该项目的用发非常简单,首先从Github上克隆到本地 git clone https://github.com/kaushil24/Artificial-Eyeliner/接下来,打开命令提示符并键入以下代码以运行示例测试python3 eyeliner.py -v "Media/Sample Video.mp4"我们也可以通过将视频路径放在参数中来使用自己的视频。完整的CLI命令如下:python eyeliner.py [-i image] [-v video] [-d dat] [-t thickness] [-c color] [-s save]每个参数的具体含义如下:• i :要在其上绘制眼线的图像的路径• v :要在其上绘制眼线的视频的路径。• v :也可以通过网络摄像头获取视频。例如:python3 -v webcam -s "Webcam output"• t :整数(整数)以设置眼线的厚度。默认值= 2。推荐的数值介于1-5之间• d:shape_predictor_68_face_landmarks.dat文件的路径。默认路径在根目录中。除非将shape_predictor_68_face_landmarks.dat文件存储在其他位置,否则不需要使用此参数。• c :更改眼线的颜色。语法-c 255 255 255。默认值= 0 0 0。其中每个数字代表其RGB值。• s :要将输出保存到的位置和文件名。注意程序在保存文件时会自动添加扩展名。如果已经存在同名文件,它将覆盖该文件。转载自小白学视觉公众号
-
现在,面部识别已成为生活中的一部分。因此,在介绍主题之前我们先看看实时面部识别示例。我们在手机、平板电脑等设备中使用人脸信息进行解锁的时候,这时就要求获取我们的实时面部图像,并将其储存在数据库中以进一步表明我们的身份。 通过对输入图像进行迭代和预测可以完成这个过程。同样,实时人脸识别可与OpenCV框架python的实现配合使用。再将它们组合在一个组合级别中,以实现用于实时目的的模型。 人脸识别 “面部识别”名称本身就是一个非常全面的定义,面部识别是通过数字媒体作为输入来识别或检测人脸的技术执行过程。人脸识别的准确性可以提供高质量的输出,而不是忽略影响其的问题因素。在这里,要确保运行我们的模型,必须确保在本地系统中安装了库。pip install face_recognition如果在 face_recognition库的安装过程中遇到一些问题或错误,可以点击以下链接:https://www.youtube.com/watch?v=xaDJ5xnc8dc人脸识别本身无法提供清晰的输出,因此出现了OpenCV实现的概念。OpenCV OpenCV是python中一个著名的库,用于实时应用程序。OpenCV在计算机世界中就像树的根一样非常重要。face_recognition中的OpenCV对我们训练为输入的面部图像进行聚类和特征提取。它以图像中的地标为目标,以迭代方式在计算机视觉的深度学习方法中训练它们。在本地系统中安装OpenCVpip install opencv-python使用深度学习算法,OpenCV检测可作为聚类,相似性检测和图像分类的表示。为什么我们使用OpenCV作为实时Face_Recognition中的关键工具? 人类可以轻松检测到面部,但是我们如何训练机器识别面部?OpenCV在这里填补了人与计算机之间的空白,并充当了计算机的愿景。以一个实时的例子为例,当一个人遇到新朋友时,他会记住这些人的脸,以备将来识别。一个人的大脑反复训练后端的人脸。因此,当他看到那个人的脸时,他说:“嗨,约翰!你好吗?”。对面部的识别和可以为计算机提供与人类相同的思维方式。OpenCV是计算机视觉中的重要工具。如果我们使用OpenCV,则遵循以下步骤:• 通过输入提取数据。• 识别图像中的面部。• 提取独特的特征,以建立预测思想。• 该特定人的性格特征,如鼻子,嘴巴,耳朵,眼睛和面部主要特征。• 实时人脸识别中人脸的比较。• 识别出的人脸的最终输出。使用OpenCV python的Face_Recognition: 代码下载:https://github.com/eazyciphers/deep-machine-learning-tutors/tree/master/Real-Time Face RecognitionGitHub导入所有软件包:import face_recognitionimport cv2import numpy as np加载并训练图像:# Load a sample picture and learn how to recognize it. Jithendra_image = face_recognition.load_image_file("jithendra.jpg") Jithendra_face_encoding = face_recognition.face_encodings(Jithendra_image)[0] # Load a sample picture and learn how to recognize it. Modi_image = face_recognition.load_image_file("Modi.jpg") Modi_face_encoding = face_recognition.face_encodings(Modi_image)[0]人脸编码:# Create arrays of known face encodings and their names known_face_encodings = [ Jithendra_face_encoding, Modi_face_encoding, ] known_face_names = [ "Jithendra", "Modi" ]主要方法:当实时人脸识别为true时,它将检测到人脸并按照代码中的以下步骤操作:• 抓取实时视频中的一帧。• 将图像从BGR颜色(OpenCV使用的颜色)转换为RGB颜色(face_recognition使用的颜色)• 在实时视频的帧中找到所有面部和面部编码。• 循环浏览此视频帧中的每个面孔,并检查该面孔是否与现有面孔匹配。• 如果一个人脸无法识别现有人脸,则将输出视为未知或未知。• 识别后,否则在识别出的脸部周围画一个方框。• 用其名称标记识别的面部。• 识别后显示结果图像。退出:# Hit 'q' on the keyboard to quit! if cv2.waitKey(1) & 0xFF == ord('q'): break释放摄像头的手柄:# Release handle to the webcam video_capture.release() cv2.destroyAllWindows()输入和输出 在训练过程中提供给模型的样本输入…。输入用于训练代码的样本图像样本输入图像进行训练输出
-
分割是识别图像内一个或多个对象的位置的过程。我们要介绍的技术其实非常简单,它利用了形态算子的扩张和侵蚀,以及诸如开运算,闭运算和黑帽算子的组合。01.简介安装Anaconda后,让我们从Anaconda的提示符下使用以下命令转到OpenCV安装:conda install -c https://conda.anaconda.org/menpo opencv现在,让我们从Anaconda启动器启动Spyder IDE。Anaconda启动器一旦运行了Spyder,建议验证OpenCV安装是否成功。在Python控制台的右下角,我们进行以下测试:import cv2代码讲解我们已经创建了一个启动GitHub存储库。小伙伴可以使用以下方法直接克隆它:git clone --branch step1 https://github.com/lucapiccinelli/BarcodesTutorial.git现在,我们将要下载测试图像,并对他们进行读取和显示。import cv2 import matplotlib.pyplot as plt im = cv2.imread(r’img\barcodes.jpg’, cv2.IMREAD_GRAYSCALE) plt.imshow(im, cmap=’Greys_r’)接下来,我们将对图像进行二值化处理,这样可以通过阈值的设定来提取出我们感兴趣的部分。使用黑帽运算符,我们可以增加较暗的图像元素。我们可以首先使用简单的全局阈值安全地对图像进行二值化处理。黑帽运算符使我们可以使用非常低的阈值,而不必过多地关注噪声。在应用blackhat时,我们使用的内核会更加重视垂直图像元素。内核具有固定的大小,因此可以缩放图像,这也可以提高性能(并支持某种输入归一化)。黑帽+阈值处理它遵循其他形态运算符的采用,顺序地将它们组合在一起以获得条形码位置中的连接组件。#riscalatura dell'immagine scale = 800.0 / im.shape[1] im = cv2.resize(im, (int(im.shape[1] * scale), int(im.shape[0] * scale))) #blackhat kernel = np.ones((1, 3), np.uint8) im = cv2.morphologyEx(im, cv2.MORPH_BLACKHAT, kernel, anchor=(1, 0)) #sogliatura thresh, im = cv2.threshold(im, 10, 255, cv2.THRESH_BINARY)膨胀和闭合的这种组合在测试图像上效果很好,但可能无法在其他图像上达到相同的效果。这没有关系,大家可以尝试改变参数和运算符的组合,直到对结果满意为止。膨胀+闭运算最后的预处理步骤是应用具有很大内核的开运算符,以删除太少而无法适合条形码形状的元素。kernel = np.ones((21, 35), np.uint8) im = cv2.morphologyEx(im, cv2.MORPH_OPEN, kernel, iterations=1)这是我们希望得到的最终结果:使用35x21内核打开现在,我们可以运行连接的组件的检测算法,并检索带有坐标和尺寸的条形码矩形。如大家在上一张图像中所看到的那样,最后的形态学步骤并未滤除全部的噪声。但是,在这种情况下,将它们过滤掉非常简单,以矩形区域值作为阈值就可以了。#rilettura dell'immagine, stavolta a colori im_out = cv2.imread(r'img\barcodes.jpg') #estrazione dei componenti connessi contours, hierarchy = cv2.findContours(im, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) unscale = 1.0 / scale if contours != None: for contour in contours: # se l'area non è grande a sufficienza la salto if cv2.contourArea(contour) <= 2000: continue #estraggo il rettangolo di area minima (in formato (centro_x, centro_y), (width, height), angolo) rect = cv2.minAreaRect(contour) #l'effetto della riscalatura iniziale deve essere eliminato dalle coordinate rilevate rect = \ ((int(rect[0][0] * unscale), int(rect[0][1] * unscale)), \ (int(rect[1][0] * unscale), int(rect[1][1] * unscale)), \ rect[2]) #disegno il tutto sull'immagine originale box = np.int0(cv2.cv.BoxPoints(rect)) cv2.drawContours(im_out, [box], 0, (0, 255, 0), thickness = 2) plt.imshow(im_out) #scrittura dell' immagine finale cv2.imwrite(r'img\out.png', im_out)最后,在上面的代码中,我使用提取的矩形绘制它们,并将其覆盖在原始图像上。最终结果,条形码以绿色框突出显示。结论• 提出的技术非常简单有效,但存在一些令人讨厌的缺点:• 它对条形码偏斜非常敏感;它可以很好地工作到大约45度,然后您必须执行第二遍,修改内核的方向。• 它只能在固定尺寸范围内找到条形码。• 尽管对矩形区域施加了过滤,但仍有可能无法清除某些非条形码。第一个和第二个可能不是真正的问题,但是最后一个可能会花费大家大量时间来尝试解码非条形码的内容。一个很好的解决方案是将条形码特征(图像梯度,傅立叶变换)输入给神经网络(或一些其他一些分类器),并在第二时刻过滤掉噪声。
-
小伙伴们可能会觉得从图像中提取文本是一件很麻烦的事情,尤其是需要提取大量文本时。PyTesseract是一种光学字符识别(OCR),该库提了供文本图像。PyTesseract确实有一定的效果,用PyTesseract来检测短文本时,结果相当不错。但是,当我们用它来检测表格中的文本时,算法执行失败。图1.直接使用PyTesseract检测表中的文本图1描绘了文本检测结果,绿色框包围了检测到的单词。可以看出算法对于大部分文本都无法检测,尤其是数字。而这些数字却是展示了每日COVID-19病例的相关信息。那么,如何提取这些信息?简介 在编写算法时,我们通常应该以我们人类理解问题的方式来编写算法。这样,我们可以轻松地将想法转化为算法。当我们阅读表格时,首先注意到的就是单元格。一个单元格使用边框(线)与另一个单元格分开,边框可以是垂直的也可以是水平的。识别单元格后,我们继续阅读其中的信息。将其转换为算法,您可以将过程分为三个过程,即单元格检测、区域(ROI)选择和文本提取。在执行每个任务之前,让我们先导入必要内容import cv2 as cv import numpy as np filename = 'filename.png' img = cv.imread(cv.samples.findFile(filename)) cImage = np.copy(img) #image to draw lines cv.imshow("image", img) #name the window as "image" cv.waitKey(0) cv.destroyWindow("image") #close the window单元格检测 查找表格中的水平线和垂直线可能是最容易开始的。有多种检测线的方法,这里我们采用OpenCV库中的Hough Line Transform。在应用霍夫线变换之前,需要进行一些预处理。第一是将存在的RGB图像转换为灰度图像。因为灰度图像对于Canny边缘检测而言非常重要。gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) cv.imshow("gray", gray) cv.waitKey(0) cv.destroyWindow("gray") canny = cv.Canny(gray, 50, 150) cv.imshow("canny", canny) cv.waitKey(0) cv.destroyWindow("canny")下面的两幅图分别显示了灰度图像和Canny图像。图2.灰度和Canny图像霍夫线变换 在OpenCV中,此算法有两种类型,即标准霍夫线变换和概率霍夫线变换。标准变换为我们提供直线方程,因此我们无法得知直线的起点和终点。概率变换将为我们提供线列表,即直线起点与终点的坐标值列表。我们优先选用的是概率变化。图3.霍夫线变换结果示例(来源:OpenCV)对于HoughLinesP函数,有如下几个输入参数:image -8位单通道二进制源图像。该图像可以通过该功能进行修改。rho —累加器的距离分辨率,以像素为单位。theta —弧度的累加器角度分辨率。threshold-累加器阈值参数。仅返回那些获得足够投票的行line — 线的输出向量。这里设置为无,该值保存到linesPminLineLength —最小行长。短于此的线段将被拒绝。maxLineGap —同一线上的点之间允许链接的最大间隙。# cv.HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]) → lines rho = 1 theta = np.pi/180 threshold = 50 minLinLength = 350 maxLineGap = 6 linesP = cv.HoughLinesP(canny, rho , theta, threshold, None, minLinLength, maxLineGap)为了区分水平线和垂直线,我们定义了一个函数并根据该函数的返回值添加列表。def is_vertical(line): return line[0]==line[2] def is_horizontal(line): return line[1]==line[3] horizontal_lines = [] vertical_lines = [] if linesP is not None: for i in range(0, len(linesP)): l = linesP[i][0] if (is_vertical(l)): vertical_lines.append(l) elif (is_horizontal(l)): horizontal_lines.append(l) for i, line in enumerate(horizontal_lines): cv.line(cImage, (line[0], line[1]), (line[2], line[3]), (0,255,0), 3, cv.LINE_AA) for i, line in enumerate(vertical_lines): cv.line(cImage, (line[0], line[1]), (line[2], line[3]), (0,0,255), 3, cv.LINE_AA) cv.imshow("with_line", cImage) cv.waitKey(0) cv.destroyWindow("with_line") #close the window图4.霍夫线变换结果—没有重叠滤波器重叠滤波器 检测到的线如上图所示。但是,霍夫线变换结果中有一些重叠的线。较粗的线由多个相同位置,长度不同的线组成。为了消除此重叠线,我们定义了一个重叠过滤器。最初,基于分类索引对线进行分类,水平线的y₁和垂直线的x₁。如果下一行的间隔小于一定距离,则将其视为与上一行相同的行。def overlapping_filter(lines, sorting_index): filtered_lines = [] lines = sorted(lines, key=lambda lines: lines[sorting_index]) separation = 5 for i in range(len(lines)): l_curr = lines[i] if(i>0): l_prev = lines[i-1] if ( (l_curr[sorting_index] - l_prev[sorting_index]) > separation): filtered_lines.append(l_curr) else: filtered_lines.append(l_curr) return filtered_lines实现重叠滤镜并在图像上添加文本,现在代码应如下所示:horizontal_lines = [] vertical_lines = [] if linesP is not None: for i in range(0, len(linesP)): l = linesP[i][0] if (is_vertical(l)): vertical_lines.append(l) elif (is_horizontal(l)): horizontal_lines.append(l) horizontal_lines = overlapping_filter(horizontal_lines, 1) vertical_lines = overlapping_filter(vertical_lines, 0) for i, line in enumerate(horizontal_lines): cv.line(cImage, (line[0], line[1]), (line[2], line[3]), (0,255,0), 3, cv.LINE_AA) cv.putText(cImage, str(i) + "h", (line[0] + 5, line[1]), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv.LINE_AA) for i, line in enumerate(vertical_lines): cv.line(cImage, (line[0], line[1]), (line[2], line[3]), (0,0,255), 3, cv.LINE_AA) cv.putText(cImage, str(i) + "v", (line[0], line[1] + 5), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv.LINE_AA) cv.imshow("with_line", cImage) cv.waitKey(0) cv.destroyWindow("with_line") #close the window图5.霍夫线变换结果—带重叠滤波器有了这个代码,就不会提取出重叠的行了。此外,我们还将在图像中写入水平和垂直线的索引,这将有利于ROI的选择。ROI选择 首先,我们需要定义列数和行数。这里我们只对第二行第十四行以及所有列中的数据感兴趣。对于列,我们定义了一个名为关键字的列表,将其用于字典关键字。## set keywords keywords = ['no', 'kabupaten', 'kb_otg', 'kl_otg', 'sm_otg', 'ks_otg', 'not_cvd_otg', 'kb_odp', 'kl_odp', 'sm_odp', 'ks_odp', 'not_cvd_odp', 'death_odp', 'kb_pdp', 'kl_pdp', 'sm_pdp', 'ks_pdp', 'not_cvd_pdp', 'death_pdp', 'positif', 'sembuh', 'meninggal'] dict_kabupaten = {} for keyword in keywords: dict_kabupaten[keyword] = [] ## set counter for image indexing counter = 0 ## set line index first_line_index = 1 last_line_index = 14然后,要选择ROI,我们定义了一个函数,该函数将图像(水平线和垂直线都作为输入)以及线索引作为边框。此函数返回裁剪的图像及其在图像全局坐标中的位置和大小def get_cropped_image(image, x, y, w, h): cropped_image = image[ y:y+h , x:x+w ] return cropped_image def get_ROI(image, horizontal, vertical, left_line_index, right_line_index, top_line_index, bottom_line_index, offset=4): x1 = vertical[left_line_index][2] + offset y1 = horizontal[top_line_index][3] + offset x2 = vertical[right_line_index][2] - offset y2 = horizontal[bottom_line_index][3] - offset w = x2 - x1 h = y2 - y1 cropped_image = get_cropped_image(image, x1, y1, w, h) return cropped_image, (x1, y1, w, h)裁剪的图像将用于下一个任务,即文本提取。返回的第二个参数将用于绘制ROI的边界框文字提取 现在,我们定义了ROI功能。我们可以继续提取结果。我们可以通过遍历单元格来读取列中的所有数据。列数由关键字的长度指定,而行数则由定义。首先,让我们定义一个函数来绘制文本和周围的框,并定义另一个函数来提取文本。import pytesseract pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files (x86)\Tesseract-OCR\tesseract.exe' def draw_text(src, x, y, w, h, text): cFrame = np.copy(src) cv.rectangle(cFrame, (x, y), (x+w, y+h), (255, 0, 0), 2) cv.putText(cFrame, "text: " + text, (50, 50), cv.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 0), 5, cv.LINE_AA) return cFrame def detect(cropped_frame, is_number = False): if (is_number): text = pytesseract.image_to_string(cropped_frame, config ='-c tessedit_char_whitelist=0123456789 --psm 10 --oem 2') else: text = pytesseract.image_to_string(cropped_frame, config='--psm 10') return text将图像转换为黑白以获得更好的效果,让我们开始迭代!counter = 0 print("Start detecting text...") (thresh, bw) = cv.threshold(gray, 100, 255, cv.THRESH_BINARY) for i in range(first_line_index, last_line_index): for j, keyword in enumerate(keywords): counter += 1 left_line_index = j right_line_index = j+1 top_line_index = i bottom_line_index = i+1 cropped_image, (x,y,w,h) = get_ROI(bw, horizontal, vertical, left_line_index, right_line_index, top_line_index, bottom_line_index) if (keywords[j]=='kabupaten'): text = detect(cropped_image) dict_kabupaten[keyword].append(text) else: text = detect(cropped_image, is_number=True) dict_kabupaten[keyword].append(text) image_with_text = draw_text(img, x, y, w, h, text)问题解决 这是文本提取的结果!我们只选择了最后三列,因为它对某些文本给出了奇怪的结果,其余的很好,所以我不显示它。图6.检测到的文本—版本1一些数字被检测为随机文本,即39个数据中的5个。这是由于最后三列与其余列不同。文本为白色时背景为黑色,会以某种方式影响文本提取的性能。图7.二进制图像为了解决这个问题,让我们倒数最后三列。def invert_area(image, x, y, w, h, display=False): ones = np.copy(image) ones = 1 image[ y:y+h , x:x+w ] = ones*255 - image[ y:y+h , x:x+w ] if (display): cv.imshow("inverted", image) cv.waitKey(0) cv.destroyAllWindows() return image left_line_index = 17 right_line_index = 20 top_line_index = 0 bottom_line_index = -1 cropped_image, (x, y, w, h) = get_ROI(img, horizontal, vertical, left_line_index, right_line_index, top_line_index, bottom_line_index) gray = get_grayscale(img) bw = get_binary(gray) bw = invert_area(bw, x, y, w, h, display=True)结果如下所示。结果 反转图像后,重新执行步骤,这是最终结果!算法成功检测到文本后,现在可以将其保存到Python对象(例如Dictionary或List)中。由于Tesseract训练数据中未包含某些地区名称(“ Kabupaten / Kota”中的名称),因此无法准确检测到。但是,由于可以精确检测到地区的索引,因此这不会成为问题。文本提取可能无法检测到其他字体的文本,具体取决于所使用的字体,如果出现误解,例如将“ 5”检测为“ 8”,则可以进行诸如腐蚀膨胀之类的图像处理。源代码:https://github.com/fazlurnu/Text-Extraction-Table-Image本文转自小白学视觉公众号
-
计算机视觉现在很流行,世界各地的人们都在从事某种形式的基于深度学习的计算机视觉项目。但在深度学习出现之前,图像处理技术已被用来处理和转换图像,以获得有助于我们完成任务的见解。今天,让我们看看如何实现一种简单而有用的技术,即透视投影来扭曲图像。 那么扭曲图像是什么意思?我可以用很多花哨的词和技术术语来解释它。但是,展示最终结果很容易,这样我们就可以通过观察来学习。  基础图像——主题图像——扭曲的输出 所以基本上,我们需要拍摄一个图像并剪切它以使其适合任何所需形状的画布。请注意,反过来也是可能的。现在,这已经不成问题了,让我们就来看看如何使用 OpenCV 和 Python 来实现这一点。 在进入代码的主要部分之前,我们必须首先导入必要的库。 ``` import cv2 ``` 现在,让我们按如下方式读取基本图像和主题图像。 ``` base_image = cv2.imread('base_img.jpg') ```  基本图像(左)——主体图像(右) 初始化一个数组来存储我们想要覆盖主题图像的 4 个角的坐标,我们可以使用setMouseCallback()函数手动选择这 4 个点,如下所示。 ``` def click_event(event, x, y, flags, params): ``` 在上面给出的代码片段中,我们定义了一个名为click\_event()的函数,并将其作为参数传递给setMouseCallback()函数。使用这种方法,我们将首先显示基础图像,然后我们可以手动选择图像中的四个点作为目标。我们的主题图像会扭曲到这个目标上,按下鼠标左键时记录坐标,这些存储在我们之前初始化的点数组中。选定的点以红点突出显示,如下所示。  选择角点 众所周知,我们每个人都可以按任意顺序选择 4 个点。因此需要在所选点之间保持恒定的排序。我选择以顺时针方式对点进行排序,即从左上到右上,再到右下然后到左下,这是通过如下所示的sort\_pts()方法实现的。我们使用以下事实:x 和 y 坐标的总和在左上角最小,在右下角最大。同样,它们之间的差异在右上角最小,在左下角最大。请记住,对于图像,原点位于图像的左上角。 ``` def sort_pts(points): ``` 对点进行排序后,让我们用它们来计算变换矩阵。我们创建一个名为“pts1”的 numpy 数组,它保存了主题图像的四个角的坐标。同样,我们创建一个名为“pts2”的列表,其中包含已排序的点。“pts1”的坐标顺序应该与“pts2”坐标的顺序相匹配。 ``` h_base, w_base, c_base = base_image.shape ``` 现在我们获得了扭曲对象图像所需的变换矩阵。这是使用函数cv2.getPerspectiveTransform() 获得的。由于我们希望以适合我们在基础图像中选择的框的方式变化主题图像,因此“ src ”应为“ pts1 ”,“ dst ”应为“ pts2 ”。生成的图像的大小可以指定为元组。我们确保生成的图像具有基本图像的尺寸。使用生成的矩阵,我们可以使用cv2.warpPerspective()方法扭曲图像,如给定的代码片段所示。 ``` transformation_matrix = cv2.getPerspectiveTransform(pts1, pts2) ``` 变形的图像看起来像这样:  变形的图像 下一步是创建一个蒙版,我们为其创建一个具有基本图像形状的空白图像。 ``` mask = np.zeros(base_image.shape, dtype=np.uint8) ```  初始蒙版 在这个空白蒙版上,我们绘制一个具有由“ sorted\_pts ”指定的角的多边形,并使用cv2.fillConvexPoly()方法将其填充为白色,生成的蒙版将如下所示。 ``` roi_corners = np.int32(sorted_pts) ```  填充蒙版 现在我们使用cv2.bitwise\_not()方法反转蒙版颜色。 ``` mask = cv2.bitwise_not(mask) ```  倒置蒙版 现在我们使用cv2.bitwise\_and()方法获取蒙版和基础图像并执行按位与运算。 ``` masked_image = cv2.bitwise_and(base_image, mask) ``` 这将为我们提供如下所示的图像。我们可以看到单独放置对象图像的区域是黑色的。  蒙面基础图像 最后一步是使用cv2.bitwise\_or()方法获取变形图像和蒙版图像并执行按位或运算,这将生成我们想要完成的融合图像。 ``` output = cv2.bitwise_or(warped_img, masked_image) ``` 我们做到了!我们已经成功地将一张图片叠加到另一张图片上。  融合图像 这是透视变换的一个非常简单的用例。当我们跟踪框架中物体/人物的运动时,可以使用它来生成区域的鸟瞰图。 Github代码连接: https://github.com/GSNCodes/Image\_Overlaying\_Using\_Perspective\_Transform
-
图像二值化操作 两种方法,全局固定阈值二值化和局部自适应阈值二值化全局固定阈值很容易理解,就是对整幅图像都是用一个统一的阈值来进行二值化;局部自适应阈值则是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值。效果:腐蚀操作滤波操作,模糊处理 模糊处理在边沿检测和去噪声方面有较为广泛的应用。OpenCV中提供了4种模糊算法,列举如下:averagemediangaussianbilateral这里我们只列举使用 均值滤波实现图像模糊:
-
【功能模块】在开发摄像头相关应用时,本人想采用opencv的imwrite()函数写图像数据到文件中,结果编译时提示报错。"/usr/local/ubuntu_crossbuild_devkit/sysroot//usr/lib/aarch64-linux-gnu/libpng16.so.16:对‘inflateValidate@ZLIB_1.2.9’未定义的引用"【操作步骤&问题现象】1、在mds工程中的CMakeList.txt里添加opencv相关的内容(增加了opencv库so与头文件的路径引用,以及so库名称的引用);2、代码中include opencv相关的头文件,并调用imwrite函数;3、编译提示报错。【截图信息】【日志信息】(可选,上传日志内容或者附件)LOG日志如附件“build_error_log.txt”所示。
-
Algodroid项目的主要任务是将CV系统集成到物联网解决方案中,以识别威胁生命的情况并为家中的老人提供安全。我们使用OpenCV实现计算机视觉,用于人体检测和骨骼可视化;并且我们建立了神经网络,并训练它们使用各种免费在线数据检测人类。为了分割人体骨骼,我们使用了基于TensorFlow的BodyPix。这是一个开源的ML模型,允许实时分割身体部位。该模型将人体分成24个部分,并将每个部分视为一组相同颜色的像素。分割身体后,我们的人体检测系统确定其生物力学数据,如身体几何和运动。这些参数通过OpenCV运动跟踪算法进行计算和分类。为了估计一个人的姿势,我们转向合成数据生成。通过使用仿真库,我们根据真实比例、生物特征和生物力学数据创建了人体的物理模型。我们将模型放置在虚拟环境中,并生成可能的人类行为场景。基于大约一百个场景,算法学会了估计姿态。我们建立了决策树,使估计的姿态与目标状态相匹配。这些算法将姿势与模拟场景和预测坠落的模式进行了比较。除此之外我们开发了一个通信系统,从安装在房子里的所有摄像机收集数据。在确认跌倒后,它可以发送照片并通知紧急医疗服务机构寻求进一步帮助。
-
OpenCV库在智能家庭中得到了广泛的应用,智能家庭是一种物联网系统,可以帮助人们运行智能家庭功能。物联网设备的网络可以控制灯光、调节室内温度、给植物浇水以及打开电视。提供安全是物联网家庭自动化的一个组成部分,因此,智能安全解决方案可以帮助家长照顾孩子。部署用于人员检测的计算机视觉应用程序可提高许多报警和视频对讲系统的安全性,实现OpenCV人脸识别可以防止陌生人进入房子或公寓。除了保护房屋不受入侵者的侵扰外,还必须确保独居者的安全,他们不能总是照顾自己。基于OpenCV算法和神经网络的计算机视觉人员检测系统可以远程监控老年人和有健康问题和残疾的人,在紧急情况下,他们可以提醒亲属或护理人员。在这里,我们将分享使用OpenCV构建用于实时人体检测的远程监控系统的个人经验。
-
OpenCV计算机视觉库概述 OpenCV是一组计算机视觉(CV)库,包含2500多个工具,从经典的机器学习(ML)算法到深度学习和神经网络。这是一个开源解三方库,可以在Apache许可下自由使用、修改和分发。该库与一系列操作系统兼容,包括Windows、Linux、macOS、FreeBSD、Android、iOS、BlackBerry 10,并支持用C/C++、Python和Java编写的软件。它具有强大的跨平台能力和与其他框架的兼容性。OpenCV包含一系列用于处理图像、检测和跟踪对象、描述特征以及执行许多其他任务的模块。该库配备了GPU模块,可提供高计算能力来实时捕获视频、处理图像和处理其他操作。OpenCV拥有一个庞大的全球社区,20多年来,数万名人工智能科学家、研究人员和工程师一直在为图书馆提供有价值的见解。
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签