2

このホイールスケルトン看板の円周(看板の最外周)を内側を除いて削除したいと思います。関数 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) #スケルトン化手順の後

コピーした画像で 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()

matplotlib の正しい結果

FLOODFILE を更新 + DILATE:

Floodfill-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()

残念ながらこれを取得します:

フラッドフィル+ディレート

4

3 に答える 3

1

非常に簡単な解決策は、画像内の輪郭のコンポーネントにラベルを付けることです。このような場合、直接関心のある輪郭を抽出できます。また、ラベリングはトポロジーの外側で開始されるため、最初のもの以外のすべての等高線ラベルを表示すると、結果が得られるはずです。輪郭がすでに閉じている場合、スケルトンは必要ありません! また、最初の輪郭が太い場合は、さらに細線化して細い輪郭を取得することもできます。

入力: 私

ここに画像の説明を入力

ラベル付きの等高線: L = bwlabel(~I);

ここに画像の説明を入力

最大の外側の輪郭を削除: figure, imshow(L>1)

ここに画像の説明を入力

これは、scikits接続コンポーネントのラベリング設定で複製できる必要があります。

これらのコンポーネントのサイズを計算して、それらの長さを取得することもできます (sum(sum(L==1)) など)。

于 2013-11-04T03:14:23.610 に答える
0

円形のハフ変換を使用してホイール リムの位置を特定し、そこから作業することもできます。

于 2013-05-06T08:22:52.837 に答える