2015-08-21 10 views
5

मैंने कैनी एज डिटेक्शन का उपयोग करके पानी की लहर के किनारों का पता लगाया। हालांकि, मैं इस किनारे के लिए एक वक्र फिट करना चाहता हूँ। क्या यह ओपनसीवी में संभव है? Image before edge detection.ओपनसीवी: पता लगाए गए किनारों को फिट करें

यहाँ बढ़त का पता लगाने आपरेशन का परिणाम है::

यहाँ बढ़त का पता लगाने से पहले छवि है Result after detecting

कोड OpenCV ट्यूटोरियल में एक उदाहरण से नकल किया गया था:

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 

img = cv2.imread('BW.JPG',0) 
edges = cv2.Canny(img,100,200) 

plt.plot(1),plt.imshow(edges,cmap = 'gray') 
plt.title('WAVE') 
plt.show() 

उत्तर

6

लहर बहुत सरल है, इसलिए हम cv2 के आउटपुट द्वारा परिभाषित प्राथमिक किनारे पर बहुपद वक्र फिट करेंगे। सबसे पहले हम के प्राथमिक किनारे को अंक प्राप्त करना चाहते हैं। आइए मान लीजिए कि आपकी उत्पत्ति शीर्ष पर बाईं ओर छवि पर है। मूल छवि को देखते हुए, मुझे लगता है कि अगर हम सीमा (750, 1500) में सबसे बड़े y के साथ अंक लेते हैं तो हमारे पास रुचि के हमारे बिंदुओं के लिए एक अच्छा अनुमान होगा।

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 
from numba import jit 

# Show plot 
img = cv2.imread('wave.jpg',0) 
edges = cv2.Canny(img,100,200) 

# http://stackoverflow.com/a/29799815/1698058 
# Get index of matching value. 
@jit(nopython=True) 
def find_first(item, vec): 
    """return the index of the first occurence of item in vec""" 
    for i in range(len(vec)): 
     if item == vec[i]: 
      return i 
    return -1 

bounds = [750, 1500] 
# Now the points we want are the lowest-index 255 in each row 
window = edges[bounds[1]:bounds[0]:-1].transpose() 

xy = [] 
for i in range(len(window)): 
    col = window[i] 
    j = find_first(255, col) 
    if j != -1: 
     xy.extend((i, j)) 
# Reshape into [[x1, y1],...] 
data = np.array(xy).reshape((-1, 2)) 
# Translate points back to original positions. 
data[:, 1] = bounds[1] - data[:, 1] 

हम इन बातों का ग्राफ़ बना है, तो हम वे बहुत लोगों को हम के लिए लक्ष्य कर रहे थे करने ही वाले हैं देख सकते हैं।

plt.figure(1, figsize=(8, 16)) 
ax1 = plt.subplot(211) 
ax1.imshow(edges,cmap = 'gray') 
ax2 = plt.subplot(212) 
ax2.axis([0, edges.shape[1], edges.shape[0], 0]) 
ax2.plot(data[:,1]) 
plt.show() 

extracted points

और अब है कि हम जोड़े के समन्वय की एक सरणी हम numpy.polyfit का प्रयोग कर एक सबसे फिट बहुपद के लिए गुणांक उत्पन्न करने के लिए कर सकते हैं और numpy.poly1d उन गुणांकों से समारोह उत्पन्न करने के लिए मिल गया है।

xdata = data[:,0] 
ydata = data[:,1] 

z = np.polyfit(xdata, ydata, 5) 
f = np.poly1d(z) 

और फिर साजिश

t = np.arange(0, edges.shape[1], 1) 
plt.figure(2, figsize=(8, 16)) 
ax1 = plt.subplot(211) 
ax1.imshow(edges,cmap = 'gray') 
ax2 = plt.subplot(212) 
ax2.axis([0, edges.shape[1], edges.shape[0], 0]) 
ax2.plot(t, f(t)) 
plt.show() 

showing curve

+0

एक त्रिकोणमितीय समारोह एक लहर मॉडलिंग के लिए और अधिक प्राकृतिक नहीं हैं सत्यापित करने के लिए? स्पष्ट रूप से sinusoidal में आकार। –

+0

मैं इसे आज़माउंगा! मेरी सोच यह थी कि एक बहुपद यहां बेहतर काम कर सकता है क्योंकि यह दूर बाएं और दाएं किनारे पर उथले क्षेत्रों में फिट हो सकता है। ऐसा नहीं है कि मेरा करता है, लेकिन फ़िल्टरिंग और/या कुछ बिंदुओं को छोड़कर बेहतर परिणाम मिल सकता है। –

+0

धन्यवाद क्रिस, यह सब मैं चाहता हूं। क्षमा करें कि मैंने इसे थोड़ा देर से देखा। यह मेरे लैपटॉप पर काम करता है, हालांकि मैं इसे अपने रास्पबेरी पीआई 2 पर काम नहीं कर सकता क्योंकि मुझे 'numba' स्थापित करने का कोई तरीका नहीं मिल रहा है। कोई सुझाव? – VaFancy

संबंधित मुद्दे