opencv ओपनसीवी एक 2 डी हिस्टोग्राम खींच रहा है



image-processing histogram (1)

मैं सोच रहा हूं कि ओपनसीवी सी ++ में एक एचएसवीपी मैट के 2 डी हिस्टोग्राम को साजिश कैसे करें यह प्रदर्शित करने का प्रयास करने वाला मेरा वर्तमान कोड दुविधापूर्वक विफल रहता है मैंने हिस्टोग्राम को कैसे साजिश किया है और उन सभी लोगों के बारे में देखा है जो मैंने पाया है कि वे उन्हें स्वतंत्र 1 डी हिस्टोग्राम के रूप में चित्रित करते थे।

यहां मेरा वर्तमान आउटपुट 30 अंकों वाले रंग डिब्बे और संतृप्ति डिब्बों के साथ 32 है:

यहां 7 अंक वाले रंग के डिब्बे की संख्या और संतृप्तता के डिब्बे 5 होने का एक और आउटपुट है:

मैं इसे परिणाम की तरह यहां देखना चाहता हूं

http://docs.opencv.org/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html

मैंने भी देखा जब भी मैं cout करता हूँ << Hist.size यह मुझे 50x50 देता है क्या मैं यह समझने के लिए हूँ कि इसका मतलब है कि सरणी का पहला आयाम आकार में 250 है?

साथ ही, हिस्टोग्राम को उच्चतम से निम्नतम (या इसके विपरीत) मूल्य आवृत्ति से कैसे एक तरह से होता है? यह एक और समस्या है जिसे मैं हल करने की कोशिश कर रहा हूं।

मेरा वर्तमान कार्य इस प्रकार है:

void Perform_Hist(Mat& MeanShift, Mat& Pyramid_Result, Mat& BackProj){  

  Mat HSV, Hist;

  int histSize[] = {hbins, sbins};
  int channels[] = {0, 1};

  float hranges[] = {0, 180};
  float sranges[] = {0, 256};

  const float* ranges[] = {hranges, sranges};

  cvtColor(MeanShift, HSV, CV_BGR2HSV);

  Mat PyrGray = Pyramid_Result.clone();

  calcHist(&HSV, 1, channels, Mat(), Hist, 2, histSize, ranges, true, false); 
  normalize(Hist, Hist, 0, 255, NORM_MINMAX, -1, Mat());  
  invert(Hist, Hist, 1);  
  calcBackProject(&PyrGray, 1, channels, Hist, BackProj, ranges, 1, true);

  double maxVal = 0; minMaxLoc(Hist, 0, &maxVal, 0, 0);

  int scale = 10;
  Mat histImage = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);

  for(int i = 1; i < hbins * sbins; i++){
     line(histImage,
     Point(hbins*sbins*(i-1), sbins - cvRound(Hist.at<float>(i-1))),
     Point(hbins*sbins*(i-1), sbins - cvRound(Hist.at<float>(i))),
     Scalar(255,0,0), 2, 8, 0);
  }
  imshow (HISTOGRAM, histImage);
}

क्या आप ऐसा कुछ मतलब था?

  • यह एचएसवी हिस्टोग्राम 3 डी ग्राफ के रूप में दिखाया गया है
  • V को 3 डी करने के लिए नजरअंदाज किया जाता है (अन्यथा यह 4 डी ग्राफ होगा ...)

यदि हां, तो यह कैसे करना है (मैं ओपनसीवी का उपयोग नहीं करता है, इसलिए इसे अपनी आवश्यकताओं के अनुसार समायोजित करें):

  1. स्रोत छवि को एचएसवी में कनवर्ट करें
  2. हिस्टोग्राम की गणना V मान को देखते हुए
    • वही एच के सभी रंग, एस को एकल रंग माना जाता है, चाहे कोई भी बात नहीं है,
    • आप किसी भी अन्य को अनदेखा कर सकते हैं लेकिन वी पैरामीटर सर्वोत्तम विकल्प जैसा दिखता है
  3. ग्राफ को आकर्षित करें

    • पहले गहरा रंग (एचएसवी बेस डिस्क) के साथ अंडाकार खींचें
    • फिर प्रत्येक डॉट के लिए इसी हिस्टोग्राम मान लें और उज्ज्वल रंग के साथ ऊर्ध्वाधर रेखा खींचें। हिस्टोग्राम मूल्य के लिए रेखा का आकार आनुपातिक है

यहाँ सी + + कोड है जिसके साथ मैंने यह किया है:

picture pic0,pic1,pic2,zed;

int his[65536];
DWORD w;

int h,s,v,x,y,z,i,n;
double r,a;
color c;

// compute histogram (ignore v)
pic2=pic0;                      // copy input image pic0 to pic2
pic2.rgb2hsv();                 // convert to HSV
for (x=0;x<65536;x++) his[x]=0; // clear histogram
for (y=0;y<pic2.ys;y++)         // compute it
 for (x=0;x<pic2.xs;x++)
    {
    c=pic2.p[y][x];
    h=c.db[picture::_h];
    s=c.db[picture::_s];
    w=h+(s<<8);                 // form 16 bit number from 24bit HSV color
    his[w]++;                   // update color usage count ...
    }
for (n=0,x=0;x<65536;x++) if (n<his[x]) n=his[x];   // max probability

// draw the colored HSV base plane and histogram
zed =pic1; zed .clear(999); // zed buffer for 3D
           pic1.clear(0);   // image of histogram
for (h=0;h<255;h++)
 for (s=0;s<255;s++)
    {
    c.db[picture::_h]=h;
    c.db[picture::_s]=s;
    c.db[picture::_v]=100;      // HSV base darker
    c.db[picture::_a]=0;
    x=pic1.xs>>1;               // HSV base disc position centers on the bottom
    y=pic1.ys-100;
    a=2.0*M_PI*double(h)/256.0; // disc -> x,y
    r=double(s)/256.0;
    x+=120.0*r*cos(a);          // elipse for 3D ilusion
    y+= 50.0*r*sin(a);
    z=-y;
    if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x++;
    if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y++;
    if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x--;
    if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y--;

    w=h+(s<<8);                 // get histogram index for this color
    i=((pic1.ys-150)*his[w])/n;
    c.db[picture::_v]=255;      // histogram brighter
    for (;(i>0)&&(y>0);i--,y--)
        {
        if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x++;
        if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y++;
        if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } x--;
        if (zed.p[y][x].dd>=z){ pic1.p[y][x]=c; zed.p[y][x].dd=z; } y--;
        }
    }
pic1.hsv2rgb();                 // convert to RGB to see correct colors
  • इनपुट छवि pic0 (गुलाब) है, आउटपुट छवि है pic1 (हिस्टोग्राम ग्राफ़)
  • pic2 हिस्टोग्राम अभिकलन के लिए pic0 परिवर्तित pic0
  • zed से बचने के लिए ज़ेड बफर 3 डी डिस्प्ले है ...

मैं छवियों के लिए अपनी तस्वीर वर्ग का उपयोग करता हूं इसलिए कुछ सदस्य हैं:

  • पिक्सल में xs,ys आकार का आकार
  • p[y][x].dd पिक्सेल पर (x, y) स्थिति 32 बिट पूर्णांक प्रकार के रूप में है
  • clear(color) - पूरी छवि को साफ करता है
  • resize(xs,ys) - नए संकल्प पर छवि का आकार बदलता है
  • rgb2hsv() और hsv2rgb() ... लगता है कि यह क्या करता है :)

[2 संपादित करें] 2 डी हिस्टोग्राम

ऐसा लगता है कि आपके पास रंग 2 डी सरणी में कोडित है एक अक्ष H और दूसरा S इसलिए आपको सर पता से H,S मान की गणना करने की आवश्यकता है। यदि यह रैखिक है तो HSV[i][j] :

  • H=h0+(h1-h0)*i/maxi
  • S=s0+(s1-s0)*j/maxj
  • या i,j उलट
  • h0,h1,s0,s1 रंग रेंज हैं
  • maxi,maxj सरणी आकार हैं

जैसा कि आप देख सकते हैं कि आप मेरे जैसे V भी छोड़ देते हैं, इसलिए हिस्टोग्राम 2 डी सरणी में प्रत्येक कक्ष के लिए आपको H,S । जहां संभावना सेल मूल्य है अब अगर आप एक छवि खींचना चाहते हैं तो आपको यह पता होना चाहिए कि यह कैसे आउटपुट करना है (2 डी ग्राफ, 3 डी, मानचित्रण, ...) के रूप में। Unsorted 2D ग्राफ़ ड्रा ग्राफ़ के लिए जहां:

  • x=i+maj*i
  • y=HSV[i][j]
  • color=(H,S,V=200);

अगर आप इसे सॉर्ट करना चाहते हैं, तो बस एक्स अक्ष को अलग तरह से गणना करें या सॉर्ट क्रम में 2 डी सरणी में लूप करें और एक्स बस वेतन वृद्धि

[संपादित करें] कोड का अद्यतन और कुछ चित्र

मैंने ऊपर C ++ कोड की मरम्मत की है (गलत Z मान चिन्ह, परिवर्तित Z बफर स्थिति और अच्छे आउटपुट के लिए बड़ा अंक जोड़ा है)। आपके 2 डी सरणी रंग इस रूप में हो सकते हैं:

जहां एक अक्ष / इंडेक्स H , अन्य S और Value निश्चित है (मैं 200 चुनें)। यदि आपके अक्षरों को स्वैप किया जाता है तो बस y=x मुझे मिरर लगता है ...

रंग सॉर्टिंग वास्तव में सिर्फ एक ऑर्डर है जिसमें आप सरणी से सभी रंग चुनते हैं। उदाहरण के लिए:

v=200; x=0;
for (h=0;h<256;h++)
 for (s=0;s<256;s++,x++)
 {
 y=HSV[h][s];
 // here draw line (x,0)->(x,y) by color hsv2rgb(h,s,v); 
 }

यह वृद्धिशील तरीका है आप अलग-अलग सॉर्टिंग या fors स्वैप प्राप्त करने के बजाय H,S से x गणना कर सकते हैं ( x++ इनर लूप में होना चाहिए)

यदि आप आरजीबी हिस्टोग्राम प्लॉट चाहते हैं तो देखें:

  • उद्देश्य सी के साथ छवि के आरजीबी रंग हिस्टोग्राम को कैसे साजिश करना