我想删除这个车轮骨架标志的圆周(标志的最外边界),除了里面的内容。 我想一个函数findcontours()并删除我找到的最大轮廓
这是输入图像:
镂空:
但遗憾的是这是我的输出图片:
为什么它不仅仅留有2个交叉段而且段由许多点组成
from __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<area):
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)#after skeletonization procedure
我可以将find_contour与复制的图像一起使用,并将draw_contour应用于原始图像,这就是全部!
我的问题是:
为什么找到轮廓编辑我的图像而我被迫使用临时图像? 为什么matplotlib给我看正确的结果而cv2 imshow没有(它给我看一个黑色的图像)?
代码的新部分:
import 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:
洪水填充扩张程序是否正确? 哪个'错了?
a = 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()
我很遗憾地得到了这个:
答案 0 :(得分:1)
您可以实现所需结果的另一种方法是对镂空图像进行泛光填充。由于外边界是闭合的,它将选择对象外的所有像素。然后可以应用简单的扩张以扩展填充区域以包括外环。将其作为遮罩应用,并移除任何已充满洪水+扩张的像素。这将只留下车轮的中心。
答案 1 :(得分:1)
一个非常简单的解决方案是在图像中标记轮廓的组成部分。在这种情况下,您可以提取您感兴趣的轮廓。并且由于标签在拓扑之外开始,如果显示除第一个之外的所有轮廓标签,则应该得到结果。在轮廓已经关闭的情况下,不需要骨架!如果我们开始使用的是厚的,也可以进一步使用细化来获得薄的轮廓。
输入:我
标记轮廓:L = bwlabel(~I);
去除最大外轮廓:图,imshow(L&gt; 1)
必须能够在scikits连接的组件标签设置中进行复制。
您还可以计算这些组件的大小并获取它们的长度(总和(总和(L == 1))等等)
答案 2 :(得分:0)
您还可以使用圆形Hough变换来尝试找到轮辋,然后从那里开始工作。