我想删除此车轮骨架标志的周长(标志的最外面的周长),除了里面的什么。
我考虑一个函数findcontours()并删除我发现的最大轮廓
这是输入图像:
骨骼化:
不幸的是,这是我的输出图像:
为什么它不只保留2个交叉的线段,而是由许多点组成一个线段
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
82
83
84from __future__ import division
import mahotas as mh
import pymorph as pm
import numpy as np
import os
import math
import cv2
from skimage import io
import scipy
from skimage import morphology
complete_path = 'DUPLInuova/ruote 7/e (11).jpg'
fork = mh.imread(complete_path)
fork = fork[:,:,0]# extract one component, ex R
#structuring elements
disk7 = pm.sedisk(3)#size 7x7: 7=3+1+3
disk5 = pm.sedisk(2)
#Just a simple thresholding with white background
bfork = fork < 150
bfork = mh.morph.dilate(bfork, disk7)
gray = cv2.imread(complete_path,0)
originale = gray
print("gray")
print(gray.shape)
cv2.imshow('graybin',gray)
cv2.waitKey()
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
imgbnbin = thresh
print("shape imgbnbin")
print(imgbnbin.shape)
cv2.imshow('binaria',imgbnbin)
cv2.waitKey()
shape = list(gray.shape)
w = int( (shape[0]/100 )*5)
h = int((shape[1]/100)*5)
print(w)
print(h)
element = cv2.getStructuringElement(cv2.MORPH_CROSS,(w,h)) #con 4,4 si vede tutta la stella e riconosce piccoli oggetti
from skimage.morphology import square
graydilate = np.array(imgbnbin, dtype=np.float64)
graydilate = morphology.binary_dilation(graydilate, square(w))
graydilate = morphology.binary_dilation(graydilate, square(w))
out = morphology.skeletonize(graydilate>0)
img = out.astype(float)
cv2.imshow('scikitimage',img)
cv2.waitKey()
img = img.astype(np.uint8)
cv2.imshow('scikitconvert',img)
cv2.waitKey()
contours, hierarchy = cv2.findContours(img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
# calculating area for deleting little signs
Areacontours = list()
calcarea = 0.0
unicocnt = 0.0
for i in range (0, len(contours)):
area = cv2.contourArea(contours[i])
#print("area")
print(area)
if (area > 90 ):
if (calcarea
calcarea = area
unicocnt = contours[i]
cnt = unicocnt
ara = cv2.contourArea(cnt)
print("cnt")
print(ara)
#delete largest contour
cv2.drawContours(img,[cnt],0,(0,255,0),1)
cv2.imshow('img del contour',img)
cv2.waitKey()
更新解决方案(和新问题):
如果我在此代码行之后对框架化的img做一个深拷贝:
img = img.astype(np.uint8)#框架化程序之后
我可以将find_contour与复制的图像一起使用,并将draw_contour应用于原始图像,仅此而已!
我的问题是:
为什么要找到轮廓来编辑图像并被迫使用临时图像?
为什么matplotlib向我显示正确的结果而cv2 imshow不显示(向我显示黑色图像)?
代码的新部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import copy
imgcontour = copy.copy(img)
imgcnt = img
contours, hierarchy = cv2.findContours(imgcontour,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE )
print(len(contours))
cnt = contours[0]
cv2.drawContours(img,[cnt],0,(0,0,0),1)
cv2.imshow('imgcv2black',img)
cv2.waitKey()
plt.gray()
plt.subplot(121)
plt.imshow(img)
plt.show()
更新FLOODFILE + DILATE:
充水膨胀程序正确吗?
哪里错了?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17a = np.ones((212,205), dtype=np.uint8)
#myMask = zeros(a.shape[0:2], dtype = uint8)
maskr = np.zeros(a.shape,np.uint8)
print(maskr.shape)
print(img[0])
cv2.floodFill(img,mask =maskr, seedPoint = (0,0), newVal = 1)
element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
img = cv2.dilate(img, element)
cv2.imshow('flood',img)
cv2.waitKey()
plt.gray()
plt.subplot(121)
plt.imshow(img)
plt.show()
和我不幸的是获得:
一个非常简单的解决方案是标记图像中轮廓的组成部分。在这种情况下,您可以提取您直接感兴趣的轮廓。而且,由于标签从拓扑结构的外部开始,因此,如果显示的轮廓标签不是第一个,则应该得到结果。如果轮廓已经闭合,则无需骨架!如果我们开始的轮廓很粗,也可以进一步使用细化获得轮廓。
输入:我
标记轮廓:L = bwlabel(?I);
去除最大的外部轮廓:数字,imshow(L> 1)
必须能够在scikits连接的组件标签设置中进行复制。
您还可以计算这些组件的大小并获取它们的长度(sum(sum(L == 1)),依此类推)
您可能会获得所需结果的另一种方法是对框架化图像进行泛洪填充。由于外部边界是封闭的,它将选择对象外部的所有像素。然后可以应用简单的膨胀来扩大填充区域以包括外环。将此应用为遮罩,并删除所有已被洪水填充+扩散的像素。这将只留下轮子的中心。
您也可以使用圆形霍夫变换来尝试找到轮辋,然后从那里开始工作。