2012-06-29 22 views
11

मैं ब्लॉब्स का पता लगाने के लिए ओपनसीवी में एक एंड्रॉइड ऐप लिख रहा हूं। एक कार्य पृष्ठभूमि से अग्रभूमि वस्तुओं को अलग करने के लिए छवि को थ्रेसहोल्ड करना है (छवि देखें)।हिस्टोग्राम से थ्रेसहोल्ड मूल्य कैसे प्राप्त करें?

यह तब तक ठीक काम करता है जब तक छवि ज्ञात हो और मैं थ्रेसहोल्ड() को थ्रेसहोल्ड मान मैन्युअल रूप से पास कर सकता हूं - इस विशेष छवि में 200 कहें। लेकिन यह मानते हुए कि छवि केवल एकमात्र ज्ञान के साथ ज्ञात नहीं है एक गहरा ठोस पृष्ठभूमि और लाइटर फोरग्राउंड ऑब्जेक्ट्स मैं गतिशील रूप से थ्रेसहोल्ड वैल्यू को कैसे समझ सकता हूं?

मैं हिस्टोग्राम में आया हूं जहां मैं ग्रेस्केल छवि की तीव्रता वितरण की गणना कर सकता हूं। लेकिन मुझे हिस्टोग्राम का विश्लेषण करने और उस मूल्य का चयन करने का तरीका नहीं मिला जहां ब्याज की वस्तुएं (लाइटर) झूठ बोलती हैं। अर्थात्; मैं हल्के अग्रभूमि स्पाइक्स से स्पष्ट रूप से अंधेरे पृष्ठभूमि की स्पाइक्स को अलग करना चाहता हूं - 200 से ऊपर इस मामले में, लेकिन एक और मामले में, 100 कह सकता है कि वस्तुएं भूरे रंग के हैं।

enter image description here

+4

वहाँ एक इसके लिए तरीकों का गुच्छा। शायद ओत्सु का तरीका आपके लिए काम कर सकता है। यदि नहीं, तो यह अभी भी एक अच्छा प्रारंभिक बिंदु IMHO है। http://en.wikipedia.org/wiki/Otsu%27s_Method – Florian

+0

क्या आप छवि अपलोड कर सकते हैं जिस पर 100 थ्रेसहोल्ड अच्छा है? क्योंकि 50 थ्रेसहोल्ड से ऊपर की छवि पर भी स्वीकार्य है ... – ArtemStorozhuk

उत्तर

9

यदि आपकी सभी छवियां इस तरह हैं, या इस शैली में लाया जा सकता है, तो मुझे लगता है कि cv2.THRESHOLD_OTSU, यानी ओत्सु का ट्रेसहोल्डिंग एल्गोरिदम एक अच्छा शॉट है।

>>> import cv2 
>>> import numpy as np 
>>> img2 = cv2.imread('D:\Abid_Rahman_K\work_space\sofeggs.jpg',0) 

>>> ret,thresh = cv2.threshold(img2,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) 

>>> ret 
122.0 

ret सीमा मूल्य जो स्वचालित रूप से गणना की जाती है है:

नीचे एक नमूना आदेश टर्मिनल में अजगर का उपयोग कर रहा है। हम इसके लिए '0' को थ्रेसहोल्ड मान के रूप में पास करते हैं।

मुझे जीआईएमपी में 124 मिल गया (जो परिणाम के मुकाबले तुलनात्मक है)। और यह शोर को भी हटा देता है। परिणाम नीचे देखें:

enter image description here

6

आप का कहना है कि पृष्ठभूमि अंधेरे (काला) है और अग्रभूमि हल्का होता है, तो मैं YUV color space (या किसी अन्य YXXYCrCb, आदि) का उपयोग करने के, की सिफारिश क्योंकि इस तरह के रंग रिक्त स्थान का पहला घटक ल्यूमिनेंस (या बिजली) है।

histogram

पहले देखें (:

light channel

तो बाद वाई चैनल (extractChennel समारोह के माध्यम से) निकाला जाता है हम इस चैनल के हिस्टोग्राम (छवि) का विश्लेषण करने की जरूरत है बाएं) कूबड़? यह आपकी छवि पर अंधेरे क्षेत्रों (आपकी स्थिति में पृष्ठभूमि) का प्रतिनिधित्व करता है। तो हमारा लक्ष्य अब एक सेगमेंट ढूंढना है (abscissa पर, यह छवि में लाल हिस्सा है) जिसमें यह कूल्हे है। जाहिर है इस सेगमेंट का बायां बिंदु शून्य है।

  • (स्थानीय) हिस्टोग्राम की अधिकतम बिंदु
  • हिस्टोग्राम का मूल्य कुछ छोटे एप्सिलॉन से भी कम है के बाईं ओर से है (यदि आप इसे करने के लिए सेट कर सकते हैं: सही बिंदु पहला बिंदु जहां है 10)

मैंने इस हिस्टोग्राम में सेगमेंट के दाएं बिंदु के स्थान को दिखाने के लिए एक हरे रंग की लंबवत रेखा खींची।

और यही वह है! सेगमेंट का यह सही बिंदु आवश्यक थ्रेसहोल्ड है। यहाँ परिणाम है (एप्सिलॉन 10 और गणना की सीमा 50 है):

result

मुझे लगता है कि यह एक समस्या नहीं है आप ऊपर छवि में शोर को नष्ट करने के लिए।

0

निम्नलिखित एक सी ++ आबिद के जवाब के कार्यान्वयन कि OpenCV 3.x के साथ काम करता है:

// Convert the source image to a 1 channel grayscale: 
Mat gray; 
cvtColor(src, gray, CV_BGR2GRAY); 
// Apply the threshold function with the CV_THRESH_OTSU setting as well 
// You can skip having it return the value, but I include it for showing the 
// results from OTSU 
double thresholdValue = threshold(gray, gray, 0, 255, CV_THRESH_BINARY+CV_THRESH_OTSU); 
// Present the threshold value 
printf("Threshold value: %f\n", thresholdValue); 

मूल छवि के खिलाफ इस चल रहा है, मैं निम्नलिखित हो: enter image description here

ओपनसीवी ने इसके जवाब में पाए गए मूल्य एबिड के करीब 122 के थ्रेसहोल्ड मान की गणना की।

बस सत्यापित करने के लिए, मैं मूल छवि बदल के रूप में यहां देखी गई:

enter image description here

और निम्नलिखित का उत्पादन किया, 178 की एक नई सीमा मूल्य के साथ:

enter image description here

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