如何检测角落的“关节"?连接图像上的元素? [英] How to detect corner "joints" that connect elements on images?
问题描述
我正在通过Python 3.7使用OpenCV.我有一组像这样的单色图像:
我想在这些图像上找到所有的连接点",其中连接点"-是两个木板的每个交叉点的中心(1像素).这些关节"在下面的图片中用红色ci粗略表示:
第一个想法是对图像进行骨架化,然后从算法上找到所有连接的边缘,但是所有骨架化技术都给了我摆动或圆角以及多余的新芽".
import cv2将numpy导入为np从skimage.morphology导入骨架化图片= cv2.imread("SOURCE_IMAGE.jpg",cv2.IMREAD_GRAYSCALE)binary_image = cv2.adaptiveThreshold(image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,91,12)骨架=(骨架化(binary_image//255)* 255).astype(np.uint8)
结果:
第二个想法是找到内部轮廓,将它们逼近边界点,找到最接近的邻居,然后以某种方式计算中心,但是,Canny边缘检测方法又给了我弯曲的拐角和额外的点.
import cv2图片= cv2.imread("SOURCE_IMAGE.jpg",cv2.IMREAD_GRAYSCALE)edged = cv2.Canny(image,100,200)
结果:
这个问题有可靠的解决方法吗?
以下是
结果
import cv2将numpy导入为np#加载图像,灰度,高斯模糊,Otsus阈值图片= cv2.imread('1.jpg')灰色= cv2.cvtColor(图像,cv2.COLOR_BGR2GRAY)模糊= cv2.GaussianBlur(灰色,(3,3),0)阈值= cv2.threshold(模糊,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]#查找水平线horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,1))水平= cv2.morphologyEx(阈值,cv2.MORPH_OPEN,horizontal_kernel,迭代次数= 2)#查找垂直线vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(1,10))垂直= cv2.morphologyEx(阈值,cv2.MORPH_OPEN,垂直内核,迭代次数= 2)#查找关节关节= cv2.bitwise_and(水平,垂直)#查找关节的质心cnts = cv2.findContours(关节,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)如果len(cnts)== 2,则cnts = cnts [0]否则,cnts [1]对于C中的cnts:#找到质心并绘制中心点M = cv2.moments(c)cx = int(M ['m10']/M ['m00'])cy = int(M ['m01']/M ['m00'])cv2.circle(image,(cx,cy),3,(36,255,12),-1)cv2.imshow('thresh',thresh)cv2.imshow(水平",水平)cv2.imshow('垂直',垂直)cv2.imshow('关节',关节)cv2.imshow('image',image)cv2.waitKey()
I'm using OpenCV via Python 3.7. I have a set of monochrome images that look like this:
I'd like to find all "joint points" on these images, where a "joint point" - is a center (1 pixel) of every intersection of two planks. These "joints" are roughly represented by red cicrles on the image below:
The first idea was to skeletonize the image and then find all connected edges algorythmically, but all skeletonizations technques gave me wiggly or round corners and extra "sprouts".
import cv2
import numpy as np
from skimage.morphology import skeletonize
image = cv2.imread("SOURCE_IMAGE.jpg", cv2.IMREAD_GRAYSCALE)
binary_image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 91, 12)
skeleton = (skeletonize(binary_image//255) * 255).astype(np.uint8)
Result:
The second idea was to find inner contours, approximate them to bounding points, find closest neighbours and then somehow calculate centers, but, again, Canny edge detection method gave me wiggly corners and extra points.
import cv2
image = cv2.imread("SOURCE_IMAGE.jpg", cv2.IMREAD_GRAYSCALE)
edged = cv2.Canny(image, 100, 200)
Result:
Are there any reliable approcahes to this problem?
Here's a slight modified version of @YunusTemurlenk's approach using Python instead of C++. The idea is:
Obtain binary image. Load image, convert to grayscale, Gaussian blur, then Otsu's threshold.
Obtain horizontal and vertical line masks. Create horizontal and vertical structuring elements with
cv2.getStructuringElement
then performcv2.morphologyEx
to isolate the lines.Find joints. We
cv2.bitwise_and
the two masks together to get the joints.Find centroid on joint mask. We find contours then calculate the centroid.
Horizontal/vertical line masks
Detected joints in green
Results
import cv2
import numpy as np
# Load image, grayscale, Gaussian blur, Otsus threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Find horizonal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,1))
horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
# Find vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,10))
vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
# Find joints
joints = cv2.bitwise_and(horizontal, vertical)
# Find centroid of the joints
cnts = cv2.findContours(joints, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
# Find centroid and draw center point
M = cv2.moments(c)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cv2.circle(image, (cx, cy), 3, (36,255,12), -1)
cv2.imshow('thresh', thresh)
cv2.imshow('horizontal', horizontal)
cv2.imshow('vertical', vertical)
cv2.imshow('joints', joints)
cv2.imshow('image', image)
cv2.waitKey()
这篇关于如何检测角落的“关节"?连接图像上的元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!