如何检测角落的“关节"?连接图像上的元素? [英] How to detect corner "joints" that connect elements on images?

查看:42
本文介绍了如何检测角落的“关节"?连接图像上的元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过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]#查找水平线horizo​​ntal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(10,1))水平= cv2.morphologyEx(阈值,cv2.MORPH_OPEN,horizo​​ntal_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:

  1. Obtain binary image. Load image, convert to grayscale, Gaussian blur, then Otsu's threshold.

  2. Obtain horizontal and vertical line masks. Create horizontal and vertical structuring elements with cv2.getStructuringElement then perform cv2.morphologyEx to isolate the lines.

  3. Find joints. We cv2.bitwise_and the two masks together to get the joints.

  4. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆