当前位置:   article > 正文

图片中线段和圆圈检测(python opencv)

图片中线段和圆圈检测(python opencv)

在这里插入图片描述

前言

本文实现将一个图片中的线段和圆圈检测出来,效果就像这样

企业微信截图_17046860711812.png

开始之前请先自行安装 opencv

另外还用到了一个用来检测直线: http://olena.pages.lre.epita.fr/pylena/index.html

pip install pylena
  • 1

直线检测

先用 opencv 来检测直线, 因为下面代码是运行在 google 实验室的,所以显示图片使用 google.colab.patches 提供的方法

import cv2
import numpy as np
from google.colab.patches import cv2_imshow
import sys
import math
import matplotlib.pyplot as plt

# 读取原始图像 
image = cv2.imread("/content/2.jpg") 

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

kernel = np.ones((1))
img_dilated = cv2.dilate(gray, kernel, iterations=1) 

# 使用Canny边缘检测算法 
edges = cv2.Canny(img_dilated, 100, 200)

# 使用Hough线变换算法检测线
lines = cv2.HoughLinesP(edges,1,np.pi/180, threshold=25, minLineLength=20, maxLineGap=20)

# 绘制检测到的线
for line in lines:
    x1, y1, x2, y2 = line[0]
    cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
 
# 显示结果
print(f"共: {len(lines)} 条线段")
cv2_imshow(image)
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

效果是这样的,虽然也都差不太多了,但是还得手动处理一些数据才行,因为重复的和没用的线段有些多,都需要删除掉才行。
企业微信截图_17046763521427.png

那就换一个库,使用 pylena

import matplotlib.pyplot as plt
from skimage.data import text
from skimage import io, color
import pylena as pln
import numpy as np 
from skimage import img_as_ubyte  # 用于将图像转换为 uint8 类型
from typing import List
import random
import cv2 


def random_red_color():
    # 随机生成红色通道值
    red_channel = 255
    green_channel = random.randint(0, 255)
    blue_channel = random.randint(0, 255)

    # 返回RGB颜色
    return (red_channel, green_channel, blue_channel)

# 转换为 uint8 类型
img2 = img_as_ubyte(color.rgb2gray(img.copy())) 
plt.xticks([])
plt.yticks([]) 

img_label: np.ndarray
superpositions: List[pln.scribo.LSuperposition]
lines: List[pln.scribo.VSegment]
 
img_label,superpositions, lines = pln.scribo.line_detector(
    img2, 
    "full", verbose=False, 
    min_len=50, 
    blumi=160, 
    llumi=160, 
    discontinuity_relative=0, 
    minimum_for_fusion=0
)
print(f"共检测出:{len(lines)}条线段")
 
if lines is not None:
    for line in lines:  
        cv2.line(img, (line.x0, line.y0), (line.x1, line.y1), random_red_color(), 2) 
else:
    print("未检测出直线")


plt.xticks([])
plt.yticks([]) 

plt.imshow(img)
plt.show()
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

效果如下,但是每一次检测都是不一样的结果,差距倒是不大。
image.png

完善下代码,将圆圈也检测一些,圆圈检测使用 opencv

import matplotlib.pyplot as plt
from skimage.data import text
from skimage import io, color
import pylena as pln
import numpy as np 
from skimage import img_as_ubyte  # 用于将图像转换为 uint8 类型
from typing import List
import random
import cv2


def random_red_color():
    # 随机生成红色通道值
    red_channel = 255
    green_channel = random.randint(0, 255)
    blue_channel = random.randint(0, 255)

    # 返回RGB颜色
    return (red_channel, green_channel, blue_channel)


# ==== 圆形检测 ==== 
img = io.imread("/content/1.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(
    gray,
    cv2.HOUGH_GRADIENT,
    dp=1,
    minDist=50,
    param1=100,
    param2=25,
    minRadius=5,
    maxRadius=100
)
print(f"共检测出:{len(circles[0])}个圆") 
if circles is not None:
    circles = np.uint16(np.around(circles))
    for circle in circles[0, :]:
        center = (circle[0], circle[1])
        # radius = circle[2]
        radius = 30 # 别超过下面直线的最大检测长度
        cv2.circle(img, center, radius, random_red_color(), 2)
else:
    print("未检测出圆圈")

# plt.imshow(img)
# plt.show()



# ==== 直线检测 ==== 
# 转换为 uint8 类型
img2 = img_as_ubyte(color.rgb2gray(img.copy())) 
plt.xticks([])
plt.yticks([]) 

img_label: np.ndarray
superpositions: List[pln.scribo.LSuperposition]
lines: List[pln.scribo.VSegment]
 
img_label,superpositions, lines = pln.scribo.line_detector(
    img2, 
    "full", verbose=False, 
    min_len=50, 
    blumi=160, 
    llumi=160, 
    discontinuity_relative=0, 
    minimum_for_fusion=0
)
print(f"共检测出:{len(lines)}条线段")
 
if lines is not None:
    for line in lines:  
        cv2.line(img, (line.x0, line.y0), (line.x1, line.y1), random_red_color(), 2) 
else:
    print("未检测出直线")
 
plt.imshow(img)
plt.show()


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

image.png

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/651363
推荐阅读
相关标签
  

闽ICP备14008679号