सबसे पहले: समारोह minMaxLoc
केवल वैश्विक न्यूनतम और किसी दिए गए इनपुट के लिए वैश्विक अधिकतम पाता है, तो यह ज्यादातर क्षेत्रीय न्यूनतम और/या क्षेत्रीय मॅक्सिमा निर्धारण करने के लिए बेकार है। लेकिन आपका विचार सही है, मार्करों के आधार पर वाटरशेड ट्रांसफॉर्म करने के लिए क्षेत्रीय मिनीमा/मैक्सिमा के आधार पर मार्कर निकालने के लिए बिल्कुल ठीक है। मुझे वॉटरशेड ट्रांसफॉर्म क्या है और ओपनसीवी में मौजूद कार्यान्वयन का सही तरीके से उपयोग करने के तरीके को स्पष्ट करने का प्रयास करें।
वाटरशेड से निपटने वाले कुछ अच्छे कागजात इस तरह के वर्णन के समान वर्णन करते हैं (यदि आप अनिश्चित हैं, तो मुझे कुछ विवरण याद आ सकते हैं: पूछें)। आप जानते हैं कि कुछ क्षेत्र की सतह पर विचार करें, इसमें घाटियों और चोटियों (अन्य विवरणों के बीच जो हमारे लिए अप्रासंगिक हैं) शामिल हैं। मान लीजिए कि इस सतह के नीचे आपके पास पानी, रंगीन पानी है। अब, अपनी सतह की प्रत्येक घाटी में छेद बनाओ और फिर पानी सभी क्षेत्र को भरना शुरू कर देता है। कुछ बिंदु पर, अलग-अलग रंगीन पानी मिलेंगे, और जब ऐसा होता है, तो आप एक बांध बनाते हैं जैसे कि वे एक दूसरे को छूते नहीं हैं। अंत में आपके पास बांधों का संग्रह होता है, जो वाटरशेड सभी अलग-अलग रंगीन पानी को अलग करता है।
अब, यदि आप उस सतह में बहुत अधिक छेद बनाते हैं, तो आप बहुत से क्षेत्रों के साथ समाप्त होते हैं: अधिक सेगमेंटेशन।यदि आप बहुत कम करते हैं तो आपको एक सेगमेंटेशन मिलता है। तो, वस्तुतः कोई भी पेपर जो वाटरशेड का उपयोग करने का सुझाव देता है वास्तव में पेपर से निपटने वाले आवेदन के लिए इन समस्याओं से बचने के लिए तकनीकों को प्रस्तुत करता है।
मैंने यह सब लिखा है (जो किसी भी व्यक्ति के लिए संभवतः बहुत भद्दा है जो जानता है कि वाटरशेड ट्रांसफॉर्म क्या है) क्योंकि यह सीधे वाटरशेड कार्यान्वयन का उपयोग करना चाहिए (जो वर्तमान स्वीकृत उत्तर पूरी तरह से गलत तरीके से कर रहा है)। आइए पाइथन बाइंडिंग का उपयोग करके, ओपनसीवी उदाहरण पर शुरू करें।
प्रश्न में प्रस्तुत छवि कई वस्तुओं से बना है जो अधिकतर करीब हैं और कुछ मामलों में अतिव्यापी हैं। यहां वाटरशेड की उपयोगिता इन वस्तुओं को सही ढंग से अलग करना है, उन्हें एक घटक में समूहित नहीं करना है। तो आपको प्रत्येक ऑब्जेक्ट के लिए कम से कम एक मार्कर और पृष्ठभूमि के लिए अच्छे मार्करों की आवश्यकता है। उदाहरण के तौर पर, पहले ओत्सु द्वारा इनपुट छवि को बिनरिज करें और छोटी वस्तुओं को हटाने के लिए एक मोर्फोलॉजिकल ओपनिंग करें। इस चरण का परिणाम बाएं छवि में नीचे दिखाया गया है। अब बाइनरी छवि के साथ दूरी को बदलने में विचार करने पर विचार करें, परिणाम सही है।
दूरी को बदलने परिणाम के साथ
, हम कुछ सीमा ऐसी है कि हम केवल उन्हीं क्षेत्रों पृष्ठभूमि (नीचे बाईं छवि) के लिए सबसे दूर करने पर विचार करने पर विचार कर सकते हैं। ऐसा करने से, हम प्रत्येक ऑब्जेक्ट के लिए पहले थ्रेसहोल्ड के बाद विभिन्न क्षेत्रों को लेबल करके मार्कर प्राप्त कर सकते हैं। अब, हम अपने मार्कर लिखने के लिए उपरोक्त बाएं छवि के एक विस्तृत संस्करण की सीमा पर भी विचार कर सकते हैं। पूरा मार्कर नीचे दिखाया गया है (कुछ मार्कर बहुत अंधेरे हैं, लेकिन बाएं छवि में प्रत्येक सफेद क्षेत्र को सही छवि पर दर्शाया जाता है)।
यह मार्कर हम यहाँ है भावना का एक बहुत बनाता है। प्रत्येक colored water == one marker
क्षेत्र को भरना शुरू कर देगा, और वाटरशेड परिवर्तन बांधों का निर्माण करेगा ताकि अलग-अलग "रंग" विलय हो जाएं। अगर हम ट्रांसफॉर्म करते हैं, तो हमें छवि बाईं ओर मिलती है। मूल छवि के साथ उन्हें लिखकर बांधों को ध्यान में रखते हुए, हमें परिणाम सही मिलते हैं।
import sys
import cv2
import numpy
from scipy.ndimage import label
def segment_on_dt(a, img):
border = cv2.dilate(img, None, iterations=5)
border = border - cv2.erode(border, None)
dt = cv2.distanceTransform(img, 2, 3)
dt = ((dt - dt.min())/(dt.max() - dt.min()) * 255).astype(numpy.uint8)
_, dt = cv2.threshold(dt, 180, 255, cv2.THRESH_BINARY)
lbl, ncc = label(dt)
lbl = lbl * (255/(ncc + 1))
# Completing the markers now.
lbl[border == 255] = 255
lbl = lbl.astype(numpy.int32)
cv2.watershed(a, lbl)
lbl[lbl == -1] = 0
lbl = lbl.astype(numpy.uint8)
return 255 - lbl
img = cv2.imread(sys.argv[1])
# Pre-processing.
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, img_bin = cv2.threshold(img_gray, 0, 255,
cv2.THRESH_OTSU)
img_bin = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN,
numpy.ones((3, 3), dtype=int))
result = segment_on_dt(img, img_bin)
cv2.imwrite(sys.argv[2], result)
result[result != 255] = 0
result = cv2.dilate(result, None)
img[result == 255] = (0, 0, 255)
cv2.imwrite(sys.argv[3], img)
@mmgp द्वारा जवाब इस सवाल का सही समाधान है। मुझे लगता है कि आपको इसे स्वीकार्य उत्तर के रूप में चिह्नित करना चाहिए। –