赞
踩
本文实现将一个图片中的线段和圆圈检测出来,效果就像这样
开始之前请先自行安装 opencv
另外还用到了一个用来检测直线: http://olena.pages.lre.epita.fr/pylena/index.html
pip install pylena
先用 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)
效果是这样的,虽然也都差不太多了,但是还得手动处理一些数据才行,因为重复的和没用的线段有些多,都需要删除掉才行。
那就换一个库,使用 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()
效果如下,但是每一次检测都是不一样的结果,差距倒是不大。
完善下代码,将圆圈也检测一些,圆圈检测使用 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()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。