[opencv][python] 学习手册4:练习代码1

[opencv][python] 学习手册4:练习代码1

60_霍夫圆.py
61_霍夫圆_查找棋子_滑动条.py
62_查找物体的轮廓信息.py
63_查找物体的轮廓信息_绘制外接矩形.py
64_网球案例.py
64_获取轮廓相关信息.py
64_获取轮廓相关信息_优化.py


文章目录

  • [opencv][python] 学习手册4:练习代码1
    • 60_霍夫圆.py
    • 61_霍夫圆_查找棋子_滑动条.py
    • 62_查找物体的轮廓信息.py
    • 63_查找物体的轮廓信息_绘制外接矩形.py
    • 64_网球案例.py
    • 64_获取轮廓相关信息.py
    • 64_获取轮廓相关信息_优化.py
    • &&_参考
    • &&_问题解决



60_霍夫圆.py

原理

参考:圆的参数方程
参考:opencv —— HoughCircles 霍夫圆变换原理及圆检测
[opencv][python] 学习手册4:练习代码1_第1张图片

代码

"""
需求:
1. 读取图像
"""

import logging

import cv2 as cv


# 霍夫圆形检测
def hough_circle(in_gray_img):
    # 定义检测图像中圆的方法。目前唯一实现的方法是cv2.HOUGH_GRADIENT
    method = cv.HOUGH_GRADIENT
    # 累加器分辨率与图像分辨率的反比。例如,如果dp = 1,则累加器具有与输入图像相同的分辨率。如果dp = 2,则累加器的宽度和高度都是一半。
    dp = 1
    # 检测到的圆的圆心之间最小距离。如果minDist太小,则可能导致检测到多个相邻的圆。如果minDist太大,则可能导致很多圆检测不到。
    minDist = 20
    # param1 Canny算法阈值上线
    # param2 cv2.HOUGH_GRADIENT方法的累加器阈值。阈值越小,检测到的圈子越多。
    # minRadius : 最小的半径,如果不确定,则不指定
    # maxRadius : 最大的半径,若不确定,则不指定
    circles = cv.HoughCircles(in_gray_img, method, dp, minDist=minDist, param1=70, param2=30, minRadius=0, maxRadius=20)

    try:
        for circle in circles[0, :]:
            # 圆心坐标,半径
            x, y, r = circle
            # 绘制圆心
            cv.circle(img, (x, y), 2, (0, 255, 0), 1)
            # 绘制圆形
            cv.circle(img, (x, y), int(r), (0, 0, 255), 2)

        cv.imshow("result", img)
    except:
        logging.warning("霍夫圆没有找到,个数为0")


# 0. 配置日志
logging.basicConfig(level=logging.INFO)

# 1. 读取图像, 将图片转成灰色图片
# filename = r"../img/weiqi.jpg"
# filename = r"../img/water_coins.jpg"
filename = r"../img/tenis1.jpg"

img = cv.imread(filename, cv.IMREAD_COLOR)
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 调用函数,寻找霍夫圆
hough_circle(gray_img)

# 显示图像,等待按键
cv.imshow("img", img)
cv.imshow("gray", gray_img)

cv.waitKey(0)
cv.destroyAllWindows()

运行结果
[opencv][python] 学习手册4:练习代码1_第2张图片


61_霍夫圆_查找棋子_滑动条.py

代码

"""
需求:
1. 读取图像
"""

import logging

import cv2 as cv


# 霍夫圆形检测


def hough_circle(index, in_gray_img, v):
    global img
    global _dp, _minDist, _param1, _param2, _minRadius, _maxRadius

    dst = img.copy()

    # 定义检测图像中圆的方法。目前唯一实现的方法是cv2.HOUGH_GRADIENT
    method = cv.HOUGH_GRADIENT

    if index == 0:
        _dp = v  # 1
    elif index == 1:
        _minDist = v  # 20
    elif index == 2:
        _param1 = v  # 80
    elif index == 3:
        _param2 = v  # 40
    elif index == 4:
        _minRadius = v  # 10
    elif index == 5:
        _maxRadius = v  # 37

    circles = cv.HoughCircles(in_gray_img, method,
                              dp=_dp,  # 1
                              minDist=_minDist,  # 20
                              param1=_param1,  # 80
                              param2=_param2,  # 40
                              minRadius=_minRadius,  # 10
                              maxRadius=_maxRadius  # 37
                              )

    # logging.info("circles.shape={0}\ncircles=\n{1}".format(circles.shape, circles))  # x, y, radius
    logging.info("dp::{0}, minDist::{1}, _param1::{2}, _param2::{3}, _minRadius::{4}, _maxRadius::{5}".format(
        _dp, _minDist, _param1, _param2, _minRadius, _maxRadius
    ))

    for circle in circles[0, :]:
        # 圆心坐标,半径
        x, y, r = circle
        x = int(x)
        y = int(y)
        r = int(r)

        # 绘制圆心
        cv.circle(dst, (x, y), 2, (0, 255, 0), 1)
        # 绘制圆形
        cv.circle(dst, (x, y), r, (0, 0, 255), 2)

    cv.imshow("dst", dst)


# 0. 配置日志
logging.basicConfig(level=logging.INFO)

# 1. 读取图像, 将图片转成灰色图片
filename = r"../img/weiqi.jpg"  # 1, 24, 18, 33, 4, 17
# filename = r"../img/coins.jpg"  # 1, 18, 60, 20, 0, 10

img = cv.imread(filename, cv.IMREAD_COLOR)
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
gray_img = cv.GaussianBlur(gray_img, (5, 5), 0)

# 调用函数,寻找霍夫圆

# 显示图像,等待按键
cv.imshow("img", img)
cv.imshow("dst", img)
cv.imshow("gray", gray_img)

# 定义全局变量,用以存储改变值
_dp = 1
_minDist = 20
_param1 = 70
_param2 = 30
_minRadius = 0
_maxRadius = 40
cv.createTrackbar("dp", "dst", 1, 2, lambda v: hough_circle(0, gray_img, v))
cv.createTrackbar("minDist", "dst", 10, 40, lambda v: hough_circle(1, gray_img, v))
cv.createTrackbar("param1", "dst", 60, 80, lambda v: hough_circle(2, gray_img, v))
cv.createTrackbar("param2", "dst", 20, 40, lambda v: hough_circle(3, gray_img, v))
cv.createTrackbar("minR", "dst", 0, 10, lambda v: hough_circle(4, gray_img, v))
cv.createTrackbar("maxR", "dst", 10, 40, lambda v: hough_circle(5, gray_img, v))

cv.waitKey(0)
cv.destroyAllWindows()

运行结果
[opencv][python] 学习手册4:练习代码1_第3张图片


62_查找物体的轮廓信息.py

原理

# 查找轮廓
处理的图像,轮廓列表,继承关系 = cv.findContours(图像,轮廓检索模式,检索的方法)

# hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号

[opencv][python] 学习手册4:练习代码1_第4张图片

# 绘制轮廓
cv.drawContours(图像,轮廓列表,轮廓索引-1则绘制所有,轮廓颜色,轮廓的宽度)

代码

"""
需求:
1. 读取图像
"""

import logging
import cv2 as cv
import numpy as np

# 0. 配置日志
logging.basicConfig(level=logging.INFO)

# 1. 读取图像,转化成灰度图
filename = r"../img/shape.jpg"
src = cv.imread(filename, cv.IMREAD_COLOR)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. 将图像转化成二值图, block_size 表示 block_size x block_size 的正方形区域
binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 11, 5)
binary = cv.medianBlur(binary, 3)

# 3. 找出 二值图 中的轮廓
b_c, contours, hieracrchy = cv.findContours(binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
logging.info("b_c.shape::{0}\ncontours::{1}\nlen(contours)::{2}\nhieracrchy::{3}".format(
    b_c.shape, contours, len(contours), hieracrchy))  # hieracrchy::[[[-1 -1 -1 -1]]] 最外层轮廓

# 4. 绘制轮廓
cv.drawContours(src, contours, -1, (180, 180, 0), 2, cv.LINE_AA)

# 显示图像,等待按键
cv.imshow("src", src)
cv.imshow("gray", gray)
cv.imshow("binary", binary)
cv.imshow("b_c", b_c)

key = cv.waitKey(0)
logging.info("key = {0}".format(key))

运行结果
[opencv][python] 学习手册4:练习代码1_第5张图片


63_查找物体的轮廓信息_绘制外接矩形.py

代码

"""
需求:
1. 读取图像
"""

import logging
import cv2 as cv
import numpy as np

# 0. 配置日志
logging.basicConfig(level=logging.INFO)

# 1. 读取图像,转化成灰度图
# filename = r"../img/shape.jpg"
# filename = r"../img/rect_inclined.PNG"
filename = r"../img/trapezoid_inclined.PNG"
src = cv.imread(filename, cv.IMREAD_COLOR)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. 将图像转化成二值图, block_size 表示 block_size x block_size 的正方形区域
binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 11, 2)
binary = cv.medianBlur(binary, 3)

# 3. 找出 二值图 中的轮廓
"""
contours 中的 每一个 contour 存储的是一个点
"""
b_c, contours, hieracrchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# logging.info("b_c.shape::{0}\ncontours::{1}\nlen(contours)::{2}\nhieracrchy::{3}".format(
#     b_c.shape, contours, len(contours), hieracrchy))  # hieracrchy::[[[-1 -1 -1 -1]]] 最外层轮廓

# 4. 绘制轮廓
cv.drawContours(src, contours, -1, (180, 180, 0), 2, cv.LINE_AA)

# 5. 根据轮廓计算外切圆,对每一个轮廓
for contour in contours:  # 有 len(contours)个轮廓,每一个轮廓有
    # logging.info("contour::{0}\ncontour.shape::{1}".format(contour, contour.shape))  # contour.shape::(198, 1, 2), 198点
    # logging.info("{}, {}".format(len(contour), type(contour)))  # INFO:root:136, 

    # 需求1:求最小外切圆
    center, radius = cv.minEnclosingCircle(contour)
    x = int(center[0])
    y = int(center[1])
    r = int(radius)
    cv.circle(src, (x, y), r, (0, 0, 255), 2)

    # 需求2:最小外切矩形(带旋转角度,不合要求)
    """
    INFO:root:((93.92063903808594, 239.05789184570312), (77.08946228027344, 103.39725494384766), -36.11933898925781)
    左上点,右下点,角度弧度
    """
    # ret_v = cv.minAreaRect(contour)
    # # logging.info("{}".format(ret_v))
    # pt1 = ret_v[0]
    # pt2 = ret_v[1]
    # pt1 = (int(pt1[0]), int(pt1[1]))
    # pt2 = (int(pt2[0]), int(pt2[1]))
    # cv.rectangle(src, pt1, pt2, (100, 200, 250), 2)

    # 需求3:最小外切矩形
    """
    Calculates the up-right bounding rectangle of a point set or non-zero pixels of gray-scale image.
    """
    ret_v2 = cv.boundingRect(contour)
    x, y, w, h = ret_v2
    cv.rectangle(src, (x, y), (x + w, y + h), (255, 100, 0), 2)

    # 需求4:

# 显示图像,等待按键
cv.imshow("src", src)
cv.imshow("gray", gray)
cv.imshow("binary", binary)
cv.imshow("b_c", b_c)

key = cv.waitKey(0)
logging.info("key = {0}".format(key))

运行结果
[opencv][python] 学习手册4:练习代码1_第6张图片


64_网球案例.py

代码

"""
需求:
1. 读取图像
"""

import logging
import cv2 as cv
import numpy as np

# 0. 配置日志
logging.basicConfig(level=logging.INFO)

# 1. 读取图像, 转换成灰度图像
filename = r"../img/tenis1.jpg"
src = cv.imread(filename, cv.IMREAD_COLOR)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. 灰度图转换成二值图
ret_v, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_TRIANGLE)
logging.info("{}".format(ret_v))

# 3. 对二值图进行滤波处理
binary = cv.medianBlur(binary, 7)

# 4. 查找轮廓,绘制轮廓
image, contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# logging.info("{}".format(len(contours)))  # 只有一个轮廓,这个轮廓由278个点组成
cv.drawContours(src, contours, -1, (0, 0, 255), 2, cv.LINE_AA)

# 5. 计算外切圆,绘制外切圆
for contour in contours:
    # logging.info("{}, {}".format(contour, len(contour)))
    # 求最小外切圆
    center, radius = cv.minEnclosingCircle(contour)
    x, y, r = int(center[0]), int(center[1]), int(radius)
    cv.circle(src, (x, y), r, (255, 0, 0), 2)

    pass

# 显示图像,等待按键
cv.imshow("src", src)
cv.imshow("gray", gray)
cv.imshow("binary", binary)

key = cv.waitKey(0)
logging.info("key = {}".format(key))

运行结果
[opencv][python] 学习手册4:练习代码1_第7张图片


64_获取轮廓相关信息.py

代码

"""
需求:
1. 读取图像

参考:
绘制倾斜矩形轮廓的资料
1. https://my.oschina.net/u/4386741/blog/3664544
2. https://blog.csdn.net/lanyuelvyun/article/details/76614872
"""

import logging
import cv2 as cv
import numpy as np

# 0. 配置日志
logging.basicConfig(level=logging.INFO)

# 1. 读取图像, 转换成灰度图像
# filename = r"../img/tenis1.jpg"
filename = r"../img/trapezoid_inclined.PNG"
src = cv.imread(filename, cv.IMREAD_COLOR)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. 灰度图转换成二值图
ret_v, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_TRIANGLE)
# logging.info("{}".format(ret_v))

# 3. 对二值图进行滤波处理
binary = cv.medianBlur(binary, 7)

# 4. 查找轮廓,绘制轮廓
image, contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# logging.info("{}".format(len(contours)))  # 只有一个轮廓,这个轮廓由278个点组成
logging.info("contours::\n{}".format(contours))
cv.drawContours(src, contours, -1, (0, 0, 255), 2, cv.LINE_AA)

# 5. 计算外切圆,绘制外切圆
for contour in contours:
    # logging.info("{}, {}".format(contour, len(contour)))

    # 需求1:求最小外切圆
    center, radius = cv.minEnclosingCircle(contour)
    x, y, r = int(center[0]), int(center[1]), int(radius)
    img_circle = cv.circle(src, (x, y), r, (255, 0, 0), 2)

    # 需求2:求外接矩形
    ret_v = cv.boundingRect(contour)
    x, y, w, h = ret_v
    img_b_rect = cv.rectangle(src, (x, y), (x + w, y + h), (200, 100, 200), 2, cv.LINE_AA)

    # 需求3:求最小面积外接矩形(带旋转角度)(尝试实现)
    # center, size, angle = cv.minAreaRect(contour)  # 矩形中心, 宽高, angle
    rect = cv.minAreaRect(contour)
    box = cv.boxPoints(rect)
    # logging.info("box::\n{0}".format(box))
    box = np.int32(box)
    img_min_rect = cv.drawContours(src, [box], -1, (255, 255, 255), 2, cv.LINE_AA)

    # 需求4:获取周长
    ret_v = cv.arcLength(contour, closed=True)
    logging.info("ret_v::\n{0}".format(ret_v))

    # 需求5:获取面积
    ret_v = cv.contourArea(contour)
    logging.info("rect_v::\n{0}".format(ret_v))

# 显示图像,等待按键
cv.imshow("src", src)
cv.imshow("gray", gray)
cv.imshow("binary", binary)

cv.imshow("img_circle", img_circle)
cv.imshow("img_b_rect", img_b_rect)

key = cv.waitKey(0)
logging.info("key = {}".format(key))

运行结果
[opencv][python] 学习手册4:练习代码1_第8张图片


64_获取轮廓相关信息_优化.py

代码

"""
需求:
1. 读取图像

参考:
绘制倾斜矩形轮廓的资料
1. https://my.oschina.net/u/4386741/blog/3664544
2. https://blog.csdn.net/lanyuelvyun/article/details/76614872
"""

import logging
import cv2 as cv
import numpy as np

"""------------------------- 函数区 -------------------------"""


def get_min_enclose_circle(img, contour):
    center, radius = cv.minEnclosingCircle(contour)
    x, y, r = int(center[0]), int(center[1]), int(radius)
    cv.circle(img, (x, y), r, (255, 0, 0), 2)
    cv.imshow("min_enc_cir", img)


def get_bound_rect(img, contour):
    ret_v = cv.boundingRect(contour)
    x, y, w, h = ret_v
    cv.rectangle(img, (x, y), (x + w, y + h), (200, 0, 0), 2, cv.LINE_AA)
    cv.imshow("bound_rect", img)


def get_min_enclose_rect_rotate(img, contour):
    rect = cv.minAreaRect(contour)
    box = cv.boxPoints(rect)
    box = np.int32(box)
    cv.drawContours(img, [box], -1, (255, 0, 0), 2, cv.LINE_AA)
    cv.imshow("min_area_rect", img)


def get_contour_length(contour):
    ret_v = cv.arcLength(contour, closed=True)
    logging.info("ret_v::\n{0}".format(ret_v))


def get_contour_area(contour):
    ret_v = cv.contourArea(contour)
    logging.info("rect_v::\n{0}".format(ret_v))


"""------------------------- 调试区 -------------------------"""
# 0. 配置日志
logging.basicConfig(level=logging.INFO)

# 1. 读取图像, 转换成灰度图像
# filename = r"../img/tenis1.jpg"
filename = r"../img/shape_collection.PNG"
src = cv.imread(filename, cv.IMREAD_COLOR)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)

# 2. 灰度图转换成二值图
ret_v, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_TRIANGLE)

# 3. 对二值图进行滤波处理
binary = cv.medianBlur(binary, 7)

# 4. 查找轮廓,绘制轮廓
image, contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
img_contours = src.copy()
cv.drawContours(img_contours, contours, -1, (0, 0, 255), 2, cv.LINE_AA)

# 5. 对轮廓集中的每一个轮廓,计算外切圆,绘制外切圆等
min_enc_cir = src.copy()
bound_rect = src.copy()
min_enc_rect_rotate = src.copy()
for i, contour in enumerate(contours):
    logging.info("contour::{0}".format(i))

    # 需求1:求最小外切圆
    get_min_enclose_circle(min_enc_cir, contour)

    # 需求2:求外接矩形
    get_bound_rect(bound_rect, contour)

    # 需求3:求最小面积外接矩形(带旋转角度)(尝试实现)
    get_min_enclose_rect_rotate(min_enc_rect_rotate, contour)

    # 需求4:获取周长
    get_contour_length(contour)

    # 需求5:获取面积
    get_contour_area(contour)

# 显示图像,等待按键
cv.imshow("src", src)
cv.imshow("gray", gray)
cv.imshow("binary", binary)
cv.imshow("contours", img_contours)

key = cv.waitKey(0)
logging.info("key = {}".format(key))

运行结果
在这里插入图片描述


&&_参考

&&_问题解决

你可能感兴趣的:(opencv)