ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenCV-09-霍夫变换及轮廓查找(绘制 最小外接圆、旋转外接矩形、不旋转外接矩形)

2021-04-02 22:00:16  阅读:260  来源: 互联网

标签:轮廓 外接 img 线段 旋转 rgb contours 矩形 cv


1. 霍夫直线变换,是在极坐标上,对某一个点进行旋转,绘制曲线,当两条极坐标曲线相交于一点,则这两个点在一条线上,有n个点在极坐标上的曲线相交了m次,当m大于一定的阈值,则认为存在该条直线。

霍夫直线的绘制代码:

rho = 1;
theta = np.pi/180
threshold=0
lines = cv.HoughLines(img,rho, theta, threshold)

2. 绘制棋盘上的直线

在这里插入图片描述

#  霍夫变换
#  线段以像素为单位的距离精度,double类型的,推荐用1.0
rho = 1
# 线段以弧度为单位的角度精度,推荐用numpy.pi/180
theta = np.pi/180
# 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,
# 基本上意味着检出的线段越长,检出的线段个数越少。
threshold=10
# 线段以像素为单位的最小长度
min_line_length=25
# 同一方向上两条线段判定为一条线段的最大允许间隔(断裂),
# 超过了设定值,则把两条线段当成一条线段,值越大,允许线段上的断裂越大,越有可能检出潜在的直线段
max_line_gap = 3
#要求图像是8位单通道,需要先二值化
lines = cv.HoughLinesP(thresh_img,rho,theta,threshold,
						minLineLength=min_line_length,maxLineGap=max_line_gap)

3. 霍夫圆

"""
    @param 8-bit 单通道图片
    @param method 检测方法, 当前只有cv2.HOUGH_GRADIENT
    @param dp 累加器分辨率(步长)和图像分辨率的反比例, 例如:
        如果 dp=1 累加器和输入图像分辨率相同. 
        如果 dp=2 累加器宽高各为输入图像宽高的一半相同. 
    @param minDist 检测到圆的圆心之间的最小距离。
        如果参数太小,除了真实的一个之外,可能错误地检测到多个相邻的圆圈。
        如果参数太大,可能会遗漏一些圆
    @param param1 参数1。它是两个传递给Canny边缘检测器的较高阈值(较低的阈值是此值的一半)
    @param param2 参数2, 它是检测阶段圆心的累加器阈值。
        它越小,会检测到更多的假圆圈。较大累加器值对应的圆圈将首先返回。
    @param minRadius 最小圆半径.
    @param maxRadius 最大圆半径. 
        如果<=0, 会使用图片最大像素值
        如果< 0, 直接返回圆心, 不计算半径
    """
    # ../images/coins.jpg
    circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT,
                               dp = 1,
                               minDist = 50,
                               param1=160,
                               param2=50,
                               minRadius=0,
                               maxRadius=100)
    # 绘制圆
    for x,y,radius in circles[0]:
    	cv.circle(src,(x,y),radius,(200,200,0))

4. 查找和绘制轮廓

#第二项node为模式,第三项method为方法
#模式
	#RETR_EXTERNAL	只检测最外层轮廓
	#RETR_LIST	提取所有轮廓,并放置在list中,检测的轮廓不建立等级关系
	#RETR_CCOMP	提取所有轮廓,并将轮廓组织成双层结构(two-level hierarchy),
	#                       顶层为连通域的外围边界,次层位内层边界
	#RETR_TREE	提取所有轮廓并重新建立网状轮廓结构
#方法
	#CHAIN_APPROX_NONE	获取每个轮廓的每个像素,相邻的两个点的像素位置差不超过1
	#CHAIN_APPROX_SIMPLE	压缩水平方向,垂直方向,对角线方向的元素,
	#						只保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息
	#CHAIN_APPROX_TC89_L1	Teh-Chinl链逼近算法
	#CHAIN_APPROX_TC89_KCOS	Teh-Chinl链逼近算法
#返回值  处理的图像,轮廓列表,继承关系
_,contours,hierarchy = cv.findContours(img,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
# cv.drawContours(图像,轮廓列表,轮廓索引-1则绘制所有,轮廓颜色,轮廓的宽度)
cv.drawContours(img,contours,-1,(255,125,125),2)

    计算最小外接圆、最小外接矩形、周长、面积

# 外接圆
((x,y),radius) = cv.minEnclosingCircle(contour)
# 带旋转角度外接矩形  函数返回两个点坐标(共4个值)和一个旋转角度
rect1 = cv.minAreaRect(contour)
pt1 = rect1[0]  #第一个点坐标
pt2 = rect1[1]  #第二个点坐标
cv.rectangle(src,pt1,pt2,(255,255,0),1)
# 不带旋转角度外接矩形
rect2 = cv.boundingRect(contour)
# 周长
length = cv.arcLength(contour,True)  #第二个参数单标轮廓是否闭合,单位是像素
# 面积 
area = cv.contourArea(contour)

5. 实例:寻找球的外接圆

import cv2 as cv
import numpy as np

def read_rgb_img(img_name):
    rgb_img = cv.imread(img_name,cv.IMREAD_COLOR)
    cv.imshow("rgb img",rgb_img)
    return rgb_img


def convert_rgb2gray(img):
    gray_img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    # 采用高斯滤波去掉噪点
    gray_img = cv.GaussianBlur(gray_img,(5,5),0)
    cv.imshow("gray img", gray_img)

    return gray_img

def convert_gray2binary(img):
    binary_img = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY_INV,5,2)
    cv.imshow("binary img", binary_img)
    return binary_img

def filter_tenis(img,lower_color,upper_color):
    hsv_img = cv.cvtColor(img,cv.COLOR_BGR2HSV)
    # 查找颜色
    mask_img = cv.inRange(hsv_img, lower_color, upper_color)
    cv.imshow("mask img",mask_img)
    return mask_img

def getContours(img):
    _,contours,hierarchy = cv.findContours(img,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
    print(contours,hierarchy)
    return contours


def process_tenis_contours(rgb_img,contours):
    black_img = np.zeros([rgb_img.shape[0],rgb_img.shape[1],3],np.uint8)

    for c in contours:
        # 计算面积
        area = cv.contourArea(c)
        # 该函数计算曲线长度或闭合轮廓周长。
        perimeter = cv.arcLength(c,True)
        # 获取最小的外切圆
        ((x,y),radius) = cv.minEnclosingCircle(c)

        # 绘制轮廓
        cv.drawContours(rgb_img,[c],-1,(150,250,150),2)
        cv.drawContours(black_img,[c],-1,(150,250,150),2)
        # 获取轮廓中心点
        # cx,cy = get_contour_center(c)
        # print(cx,cy)
        x = int(x)
        y = int(y)
        cv.circle(rgb_img,(x,y),int(radius),(0,0,255),2)
        cv.circle(black_img,(x,y),int(radius),(0,0,255),2)

        print("Area:{},primeter:{}".format(area,perimeter))

    print("number of contours:{}".format(len(contours)))
    cv.imshow("rgb img contours",rgb_img)
    cv.imshow("black img contours",black_img)

if __name__ == '__main__':
    img_name = "assets/tenis1.jpg"
    # 定义范围
    lower_color = (30, 120, 130)
    upper_color = (60, 255, 255)

    rgb_img = read_rgb_img(img_name)
    binary_imgage = filter_tenis(rgb_img,lower_color,upper_color)

    contours = getContours(binary_imgage)
    process_tenis_contours(rgb_img,contours)

    cv.waitKey(0)
    cv.destroyAllWindows()

    效果如下:

在这里插入图片描述
彩蛋:明天是清明节啦,可以放松放松,一起加油油!

标签:轮廓,外接,img,线段,旋转,rgb,contours,矩形,cv
来源: https://blog.csdn.net/weixin_45348389/article/details/115406911

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有