2010-12-21 11 views
23

के साथ पिक्सल के माध्यम से साइकिल मैं ओपनसीवी का उपयोग करके एक छवि के माध्यम से चक्र कैसे प्राप्त कर सकता हूं जैसे कि यह प्रत्येक पिक्सेल के आरजीबी मान प्राप्त करने के लिए 2 डी सरणी था? इसके अलावा, इस ऑपरेशन के लिए एक आईप्लीमेज पर एक चटाई बेहतर होगा?ओपनसीवी

+0

संभावित डुप्लिकेट: http://stackoverflow.com/questions/998429/opencv-accessing-and-taking-the-square-root-of-pixels –

+0

मैं सिर्फ इस छोटे से समारोह मैं उपयोग करने के लिए जा रहा हूँ मिल गया। फ्लोट pixval32f (IplImage * img, int r, int c) { \t वापसी ((फ्लोट *) (img-> imageData + img-> widthStep * r)) [सी]; } –

+0

http://stackoverflow.com/questions/3859222/c-negative-rgb-values-of-pixels-using-opencv/3860920#3860920 – karlphillip

उत्तर

9

यदि आप सी ++ का उपयोग करते हैं, तो ओपनसीवी के सी ++ इंटरफ़ेस का उपयोग करें और फिर आप सदस्यों को http://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#the-efficient-way या सीवी :: मैट ::() पर उपयोग कर सकते हैं, उदाहरण के लिए।

+0

लिंक के लिए धन्यवाद! QImage :: स्कैनलाइन के समान दिखता है, बस मैं चाहता था। –

+0

जो पृष्ठ आप लिंक कर रहे हैं वह अब उपलब्ध नहीं है। – luator

37

सीवी :: चटाई IplImage से अधिक पसंद किया जाता है क्योंकि यह आपके कोड

cv::Mat img = cv::imread("lenna.png"); 
for(int i=0; i<img.rows; i++) 
    for(int j=0; j<img.cols; j++) 
     // You can now access the pixel value with cv::Vec3b 
     std::cout << img.at<cv::Vec3b>(i,j)[0] << " " << img.at<cv::Vec3b>(i,j)[1] << " " << img.at<cv::Vec3b>(i,j)[2] << std::endl; 

सरल मतलब यह है कि आप आरजीबी मानों को एक साथ उपयोग करने के लिए की जरूरत है। यदि आप नहीं करते हैं, तो आप प्रत्येक चैनल को अलग से प्राप्त करने के लिए सीवी :: स्प्लिट का उपयोग कर सकते हैं। उदाहरण के साथ लिंक के लिए इटारियन का जवाब देखें।

इसके अलावा, मेरे मामलों में, आपको बस ग्रे-स्केल में छवि की आवश्यकता है। फिर, आप छवि को ग्रेस्केल में लोड कर सकते हैं और इसे उचर की सरणी के रूप में एक्सेस कर सकते हैं।

cv::Mat img = cv::imread("lenna.png",0); 
for(int i=0; i<img.rows; i++) 
    for(int j=0; i<img.cols; j++) 
     std::cout << img.at<uchar>(i,j) << std::endl; 

अद्यतन: विभाजन का उपयोग करते हुए 3 चैनलों

cv::Mat img = cv::imread("lenna.png"); 
std::vector<cv::Mat> three_channels = cv::split(img); 

// Now I can access each channel separately 
for(int i=0; i<img.rows; i++) 
    for(int j=0; j<img.cols; j++) 
     std::cout << three_channels[0].at<uchar>(i,j) << " " << three_channels[1].at<uchar>(i,j) << " " << three_channels[2].at<uchar>(i,j) << std::endl; 

// Similarly for the other two channels 

अद्यतन प्राप्त करने के लिए: सीवी :: Vec3b उदाहरण से त्रुटि मैं शुरू की जब प्रतिलिपि करने और चिपकाने खोलना के लिए entarion के लिए धन्यवाद।

+1

यह कैसे है कि आपको वे मान मिलते हैं जो छवि के लिए गैर-पूर्णांक हैं? –

+1

'img.at (i, j) [0]' - यह काम नहीं करेगा :) '[0]' – etarion

+0

पर जाना है, मुझे इस प्रश्न पर पहुंचा है और यह मेरी समस्या का हल हो गया है, लेकिन अब मेरे पास सवाल है, क्यों :: पर काम करता है? यह अकेले पर क्यों काम नहीं करता है? की तरह (0,0)? –

3

दस्तावेज़ मैट छवि here पर पुनरावृत्त करने के विभिन्न तरीकों की अच्छी तरह लिखित तुलना दिखाते हैं।

सी शैली पॉइंटर्स का उपयोग करने का सबसे तेज़ तरीका है। यहां दस्तावेज़ों से कॉपी किया गया कोड है:

Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) 
{ 
// accept only char type matrices 
CV_Assert(I.depth() != sizeof(uchar)); 

int channels = I.channels(); 

int nRows = I.rows; 
int nCols = I.cols * channels; 

if (I.isContinuous()) 
{ 
    nCols *= nRows; 
    nRows = 1; 
} 

int i,j; 
uchar* p; 
for(i = 0; i < nRows; ++i) 
{ 
    p = I.ptr<uchar>(i); 
    for (j = 0; j < nCols; ++j) 
    { 
     p[j] = table[p[j]]; 
    } 
} 
return I; 
} 

पर तत्वों तक पहुंच काफी धीमी है।

ध्यान दें कि यदि आपका ऑपरेशन लुकअप टेबल का उपयोग करके किया जा सकता है, तो निर्मित कार्य LUT अब तक का सबसे तेज़ (दस्तावेज़ों में वर्णित) है।

9

ओपनसीवी 3.0 के बाद, सीवी :: मैट में पिक्सेल पर फ़ंक्शन चलाने के लिए आधिकारिक और तेज़ तरीका है।

void cv::Mat::forEach (const Functor& operation)

आप इस सुविधा का उपयोग करते हैं, तो ऑपरेशन है बहु कोर पर स्वचालित रूप से चलाता है।

प्रकटीकरण: मैं इस सुविधा का योगदानकर्ता हूं।

+0

काम नहीं करता है अगर यह केवल समस्या को हल करेगा, लाइब्रेरी के उपयोगकर्ता को वास्तव में प्रकारों से निपटना नहीं होगा। हो सकता है कि मुझे यह नहीं मिलता है, लेकिन किसी भी तरह यह वास्तव में "बस" पिक्सेल पढ़ने या उन्हें संशोधित करने के लिए वास्तव में कठिन है !!! –

0

यदि आप आरजीबी पिक्सल को एक-एक करके संशोधित करना चाहते हैं, तो नीचे दिया गया उदाहरण मदद करेगा!

void LoopPixels(cv::Mat &img) { 
    // Accept only char type matrices 
    CV_Assert(img.depth() == CV_8U); 

    // Get the channel count (3 = rgb, 4 = rgba, etc.) 
    const int channels = img.channels(); 
    switch (channels) { 
    case 1: 
    { 
     // Single colour 
     cv::MatIterator_<uchar> it, end; 
     for (it = img.begin<uchar>(), end = img.end<uchar>(); it != end; ++it) 
      *it = 255; 
     break; 
    } 
    case 3: 
    { 
     // RGB Color 
     cv::MatIterator_<cv::Vec3b> it, end; 
     for (it = img.begin<cv::Vec3b>(), end = img.end<cv::Vec3b>(); it != end; ++it) { 
      uchar &r = (*it)[2]; 
      uchar &g = (*it)[1]; 
      uchar &b = (*it)[0]; 
      // Modify r, g, b values 
      // E.g. r = 255; g = 0; b = 0; 
     } 
     break; 
    } 
    } 
}