添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

利用Opencv 寻找凸四边形的四个顶点
对于一个含有凸四边形的图像,要想定位出凸四边形的四个顶点的坐标。
首先,得先对图像进行边缘检测,而边缘检测的前提是二值化图像【未进行二值化的图像进行边缘检测得到的结果往往非常不理想】,根据实际图像的特点,我对图像进行二值化处理以及闭运算【主要去除目标物内的孤立点】的过程如下:

#图像灰度处理   最大值灰度
import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取第一张图像
img=cv2.imread(r"C:\Users\li1223\Desktop\DSC_0059.jpg")
gray_1 = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#BGR转换为灰度
#获取图像尺寸
h,w=img.shape[0:2]
#自定义空白单通道图像,用于存放灰度图
gray=np.zeros((h,w),dtype=img.dtype)
#对原图像进行遍历,然后分别对B\G\R按比例灰度化
for i in range(h):
    for j in range(w):
        gray[i,j]=max(img[i,j,0],img[i,j,1],img[i,j,2])#求3通道中最大的值
#gray1= cv2.cvtColor(gray,cv2.COLOR_BGR2RGB)#BGR转换为RGB显示格式,方便通过matplotlib进行图像显示
gray_avarage = np.sum(gray)/(h*w)
pp = np.where(gray>gray_avarage)
gray1 = np.zeros((h,w),dtype=img.dtype)
gray1[pp]=1
kernel = np.ones((5,5), np.uint8)
#调用opencv库膨胀函数
#img1=cv2.dilate(gray1,kernel,1)#5x5卷积核,膨胀1次
#img1=cv2.erode(gray1,kernel,1)#5x5卷积核,腐蚀1次
#opening = cv2.morphologyEx(gray1, cv2.MORPH_OPEN, kernel)#先腐蚀后膨胀
closing = cv2.morphologyEx(gray1,cv2.MORPH_CLOSE,kernel)#先膨胀后腐蚀
cv2.imshow('二值化图像',closing)
cv2.waitKey(0)

效果图:
原图
                 原图
二值化后的图
                 二值化图

  对得到的二值化图像可知,在凸四边形目标物的外围依旧有不规则孔洞和孤立小点,我们根据实际情况,如果只是有很多孤立的小点可以采用图像形态学开运算进行处理,如果有较大的不规则孔洞,可以采用联通区域的面积进行判别筛选处理。
  代码如下:

import cv2
import numpy as np
img = cv2.imread(r'C:\Users\li1223\Desktop\222.png', cv2.IMREAD_COLOR)
h, w, _ = img.shape
GrayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #图片灰度化处理
ret,binary = cv2.threshold(GrayImage,40,255,cv2.THRESH_BINARY) #图片二值化,灰度值大于40赋值255,反之0
threshold = h/20 * w/20   #设定面积阈值
#cv2.fingContours寻找图片轮廓信息
"""提取二值化后图片中的轮廓信息 ,返回值contours存储的即是图片中的轮廓信息,是一个向量,内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓,有多少轮廓,向量contours就有
多少元素"""
contours,hierarch=cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
    area = cv2.contourArea(contours[i]) #计算轮廓所占面积
    if area < threshold:                #将area小于阈值区域填充背景色,由于OpenCV读出的是BGR值
        cv2.drawContours(img,[contours[i]],-1, (0,0,0), thickness=-1)     #原始图片背景BGR值(84,1,68)
        continue
cv2.namedWindow("clahe image", 0)
cv2.resizeWindow("clahe image", 640, 480)
cv2.imshow("clahe image111", img)
cv2.waitKey(0)
cv2.imwrite(r'C:\Users\li1223\Desktop\2222.png',img)

去除目标物外点
                 去除目标物外孔洞的二值化图
  其次,将凸四边形的轮廓凸显出来(此时的轮廓含有各种毛刺边),所以再利用凸显出来的轮廓寻找凸区域勾画出轮廓的整体(去除了毛刺边)【此时,可以得到勾画轮廓的系列点,顶点也在其中】。对系列点进行椭圆拟合【通常使用最小二乘法】,可以得到椭圆质点、长短轴半径以及旋转角度【根据最小二乘法的原理得,此椭圆是不会将顶点包含在内】。最后,利用拟合所得的椭圆参数构建椭圆方程,将系列点带入计算。包含在椭圆内的点,计算值为负,在椭圆上的点,计算值为零,在椭圆外的点,计算为正。
  将计算值为正的点提取出来【顶点就在其中】构建点集,第一步挑选出计算值最大的点作为第一个顶点,然后去除第一个顶点附近的点和它本身,利用剩下的点构建一个新的点集【此时新的点集包含剩余的三个顶点以及这三个顶点附近的点】;第二步在新的点集中,挑选出计算值最大的点作为第二个顶点,然后去除第二个顶点附近的点和它本身,利用剩下的点构建一个新的点集【此时新的点集包含剩余的二个顶点以及这二个顶点附近的点】;依次类推,得到全部四个点。
假设得到椭圆质点【也称中心点】 \tfrac{(x^{'}cos\theta-y^{'}sin\theta)^{2}}{b^{2}}+\tfrac{(x^{'}sin\theta+y^{'}cos\theta)^{2}}{a^{2}}=1 b2(xcosθysinθ)2+a2 (xsinθ+ycosθ)2=1
  化解,得到
       (a^{2}cos^{2}\theta+b^{2}sin^{2}\theta)x^{'2}+(a^{2}sin^{2}\theta+b^{2}cos^{2}\theta)y^{'2}+2cos\theta sin\theta(b^{2}-a^{2})x^{'}y^{'}-a^{2}b^{2}=0 (a2cos2θ+b2sin2θ)x2+(a2sin2θ+b2cos2θ)y2+2cosθsinθ(b2a2)xya2b2=0
  则有:
      Img = cv2.imread(r'C:\Users\li1223\Desktop\2222.png') imgray = cv2.cvtColor(Img, cv2.COLOR_BGR2GRAY) B = imgray.copy() ret, thresh = cv2.threshold(imgray, 150, 255, 0) # th2 = cv2.adaptiveThreshold(imgray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2) contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) #寻找边缘 hull = cv2.convexHull(contours[len(contours)-1]) #寻找边缘的凸区域; #print(hull) cv2.polylines(Img, [hull], True, (0, 255, 0), 2) #绘制边缘 #cv2.drawContours(A,contours[0],-1,(0,0,255),3) #cv2.imshow("Perfectly11 fitted ellipses", A) #cv2.waitKey(0) elps = cv2.fitEllipseAMS(hull) #根据边缘凸区域进行椭圆拟合 cv2.ellipse(Img, elps, (0,0,255)) #绘制拟合的椭圆 center ,a_b ,angle = elps #求取拟合椭圆的中心、长短轴、旋转角度 #print(center) center_x ,center_y = center b ,a = a_b angle = angle/180*np.pi #print('elps',center_x,center_y,b,a,angle) #构建拟合椭圆的标准方程 C = math.pow(a/2*math.sin(angle),2)+math.pow(b/2*math.cos(angle),2) B = 2*(-math.pow(a/2,2)+math.pow(b/2,2))*math.sin(angle)*math.cos(angle) A = math.pow(a/2*math.cos(angle),2)+math.pow(b/2*math.sin(angle),2) f = -math.pow(a/2*b/2,2) center_array = np.array([center_x,center_y]) point_set = hull.reshape(hull.shape[0],-1) hh = point_set-center_array distance = A*np.power(hh[:,0],2)+B*hh[:,0]*hh[:,1]+C*np.power(hh[:,1],2)+f #计算边缘区域在椭圆上的值; gg = np.where(distance>0) dd = hull.reshape(hull.shape[0], -1)[gg[0],:] dd_1 = np.copy(dd) radius=8 color=(255,0,0) thickness=4 #寻找凸四边形的四个顶点 first_point = hull.reshape(hull.shape[0], -1)[np.argsort(distance)[-1:]].reshape(2, ) #第一个顶点 cv2.circle(Img, tuple(first_point), radius, color, thickness) #排除第一个顶点附近的点 a_1 = np.sqrt(np.power((first_point-dd)[:,0],2)+np.power((first_point-dd)[:,1],2)) b_1 = np.sqrt(np.power((first_point-center_array)[0],2)+np.power((first_point-center_array)[1],2)) c_1 = np.sqrt(np.power((dd-center_array)[:,0],2)+np.power((dd-center_array)[:,1],2)) cos = (np.power(b_1,2)+np.power(c_1,2)-np.power(a_1,2))/(2*b_1*c_1) - math.cos(20/180*np.pi) cos_ad = np.where(cos < 0) dd_1 = dd_1[cos_ad] dd_2 = np.copy(dd_1) hh = dd_2-center_array distance_1 = A*np.power(hh[:,0],2)+B*hh[:,0]*hh[:,1]+C*np.power(hh[:,1],2)+f #计算边缘区域在椭圆上的值; scend_point = dd_2[np.argsort(distance_1)[-1:]].reshape(2, ) #第二个顶点 cv2.circle(Img, tuple(scend_point), radius, color, thickness) #排除第二个顶点附近的点 a_2 = np.sqrt(np.power((scend_point-dd_2)[:,0],2)+np.power((scend_point-dd_2)[:,1],2)) b_2 = np.sqrt(np.power((scend_point-center_array)[0],2)+np.power((scend_point-center_array)[1],2)) c_2 = np.sqrt(np.power((dd_2-center_array)[:,0],2)+np.power((dd_2-center_array)[:,1],2)) cos_2 = (np.power(b_2,2)+np.power(c_2,2)-np.power(a_2,2))/(2*b_2*c_2) - math.cos(20/180*np.pi) cos_ad = np.where(cos_2 < 0) dd_2 = dd_2[cos_ad] dd_3 = np.copy(dd_2) hh = dd_3-center_array distance_2 = A*np.power(hh[:,0],2)+B*hh[:,0]*hh[:,1]+C*np.power(hh[:,1],2)+f #计算边缘区域在椭圆上的值; third_point = dd_3[np.argsort(distance_2)[-1:]].reshape(2, ) #第三个顶点 cv2.circle(Img, tuple(third_point), radius, color, thickness) #排除第三个顶点附近的点 a_3 = np.sqrt(np.power((third_point-dd_3)[:,0],2)+np.power((third_point-dd_3)[:,1],2)) b_3 = np.sqrt(np.power((third_point-center_array)[0],2)+np.power((third_point-center_array)[1],2)) c_3 = np.sqrt(np.power((dd_3-center_array)[:,0],2)+np.power((dd_3-center_array)[:,1],2)) cos_3 = (np.power(b_3,2)+np.power(c_3,2)-np.power(a_3,2))/(2*b_3*c_3) - math.cos(20/180*np.pi) cos_ad = np.where(cos_3 < 0) dd_3 = dd_3[cos_ad] dd_4 = np.copy(dd_3) hh = dd_4-center_array distance_3 = A*np.power(hh[:,0],2)+B*hh[:,0]*hh[:,1]+C*np.power(hh[:,1],2)+f #计算边缘区域在椭圆上的值; fourth_point = dd_4[np.argsort(distance_3)[-1:]].reshape(2, ) #第四个顶点 cv2.circle(Img, tuple(fourth_point), radius, color, thickness) cv2.circle(Img, tuple([int(center_x),int(center_y)]), radius, color=(0,0,255), thickness=10)#绘制椭圆质点 cv2.imwrite(r'C:\Users\li1223\Desktop\22222.png',Img) cv2.imshow("Perfectly fitted ellipses", Img) cv2.waitKey(0) 利用Opencv 寻找凸四边形的四个顶点  对于一个含有凸四边形的图像,要想定位出凸四边形的四个顶点的坐标。  首先,得先对图像进行边缘检测,而边缘检测的前提是二值化图像【未进行二值化的图像进行边缘检测得到的结果往往非常不理想】,根据实际图像的特点,我对图像进行二值化处理以及闭运算【主要去除目标物内的孤立点】的过程如下:#图像灰度处理 最大值灰度import cv2import numpy as npimport matplotlib.pyplot as pltplt.rcParams['

python图像处理——关于获得最小外接矩形如何获取该矩形的四个顶点坐标,以及截取进行仿射变换后矩形内的图像(cv2.boxPoints()、cv2.minAreaRect())待完善
前言在获取想要轮廓的点集后,可用cv2.minAreaRect()获取点集的最小外接矩形。返回值rect内包含该矩形的中心点坐标、高度宽度及倾斜角度等信息,使用cv2.boxPoints()可获取该矩形的四个顶点坐标。 但我们并不清楚这四个坐标点各对应着矩形的哪一个顶点,因此无法充分地利用这些坐标信息。可以从坐标值的大小特征入手,将四个坐标与矩形的四个顶点匹配起来:在opencv的坐标体系下,纵坐标最小的是top_point,纵坐标最大的是bottom_point, 横坐标最小的是left_point,横坐
本项目分别提供了以下功能:人脸图像采集,数据训练,人脸识别,删除数据。 图像采集将打开电脑摄像头获取人脸到,数据训练调用了包和xml文件(都在文件夹里),训练速度超快,人脸识别模块可以识别出训练好的人脸。 基于python3,有多个py文件,大部分为带opencv的包,没有界面但可交互,功能齐全,准确率可通过训练数据的加大提升。
如何用检测由直线构成的四边形(多边形)?  这个问题自己困扰了十来天,  查了相关的算法书 (a modern approach, algorithms and applications, computer and machine vision, Feature Extraction & Image Processing ),  并未找到直接的内容可以使用     这阵子看了一些论文,
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV用C++语言编写,它的主要接口也是C++语言,但是依然保留了大量的C语言接口。该库也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。这些语言的API接口函数可以通过在线文档获得。如今也提供对于C#、Ch、Ruby,GO的支持。 所有新的开发和算法都是用C++接口。一个使用CUDA的GPU接口也于2010年9月开始实现。
1. 定义每条线段的起点和终点坐标。假设四边形的线段分别为AB、BC、CD、DA。 2. 计算AB和CD的交点P,以及BC和DA的交点Q。可以使用向量叉积来计算两条线段是否相交,如果相交则求出交点。 3. 计算线段AB和线段CD的中点M1,以及线段BC和线段DA的中点M2。 4. 如果点P在M1和M2之间,则P是顶点之一;如果点Q在M1和M2之间,则Q是顶点之一。 5. 重复步骤2到4,可以确定四边形的所有顶点qq_42828007: gray = cv2.cvtColor(gray, cv2.COLOR_BGR2RGB) # BGR转换为RGB显示格式,方便通过matplotlib进行图像显 这句用不到吧,变成灰度图像了,二维的了,为什么还要再变回三维的