2012-11-28 11 views
9

मेरी सी ++ dll में मैं बाइट सरणी से चटाई बनाने रहा से चटाई बनाने के लिए:OpenCV बाइट सरणी

BYTE * ptrImageData; //Image data is in this array passed to this function 

Mat newImg = Mat(nImageHeight, nImageWidth, CV_8UC3, ptrImageData); 

छवि कुछ ग्रे छाया मूल एक नहीं के साथ बनाया जाता है।

क्या यह बाइट सरणी से मैट बनाने का उचित तरीका है?

कृपया कोड

ptrImageData सी # कोड से सी ++ dll में भेजा जाता है देखते हैं।

सी # कोड छवि डेटा

System.Drawing.Image srcImage //Has the image 
MemoryStream ms = new MemoryStream(); 
Marshal.FreeHGlobal(ptrImageData); 
srcImage.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
byte[] imgArray = ms.ToArray(); 
ms.Dispose(); 


int size1 = Marshal.SizeOf(imgArray[0]) * imgArray.Length; 
IntPtr ptrImageData = Marshal.AllocHGlobal(size1); 
Marshal.Copy(imgArray, 0, ptrImageData, imgArray.Length); 

//Calling C++ dll function 
ProcessImage(ptrImageData, srcImage.Width, srcImage.Height); 

Marshal.FreeHGlobal(ptrImageData); 
+1

मुझे लगता है कि आपके सी ++ कोड में कुछ गलती है, Mat newImg (...), या Mat * newImg = new Mat (..), आपका लेखन C++ शैली नहीं है। – Healer

+0

@healer .. कोड सही है। उपर्युक्त कोड में, 'MatIm'' 'MAT' वर्ग के 'स्पष्ट' कन्स्ट्रक्टर का उपयोग करके प्रारंभ किया जा रहा है। – sgarizvi

+0

कृपया अधिक विस्तृत कोड प्रदान करें, जैसे कि आप छवि कैसे दिखाते हैं, 'ptrImageData' का लेआउट क्या है। – luhb

उत्तर

0

हाँ पारित करने के लिए, यह एक तरह से एक बाइट सरणी से एक चटाई बनाने के लिए है। आपको बस सावधान रहना होगा कि आपके सरणी में वह क्या है जो आपको लगता है।

छवि कुछ ग्रे छाया के साथ बनाई गई है जो मूल नहीं है।

तो क्या आपको नई आईएमजी में एक छवि मिल रही है? मूल डेटा का पिक्सेल प्रारूप क्या था?

शायद आपने लाल और नीले चैनलों को स्विच किया है। निम्नलिखित लाइन चैनलों स्वैप जाएगा:

cv::cvtColor(newImg,swappedImg,CV_RGB2BGR); 
0

यहाँ डॉक्स के लिए लिंक है: http://docs.opencv.org/modules/core/doc/basic_structures.html#mat-mat

सामान्य तौर पर आप ध्यान रखना चाहिए के बारे में दो बातें:

  1. जब आप मैट्रिक्स निर्माता में बाहरी डेटा पास , बाहरी डेटा स्वचालित रूप से डिलीकेट नहीं किया जाता है, इसलिए आपको इसकी देखभाल करनी चाहिए। यदि आप स्मृति के बारे में देखभाल करने के लिए ओपनसीवी मैट्रिक्स चाहते हैं, तो आपको मैट्रिक्स की प्रतिलिपि बनाना चाहिए (उदाहरण के लिए आप इसे कई तरीकों से कर सकते हैं, उदाहरण के लिए Mat::clone या Mat::copyTo विधियों का उपयोग करना।
  2. बाहरी डेटा निरंतर नहीं हो सकता है, यानी पंक्ति का आकार चौड़ाई से बड़ा हो सकता है डेटा तत्व के आकार से गुणा चैनलों की संख्या से गुणा किया गया है। तो आप कन्स्ट्रक्टर के अंतिम तर्क के रूप में "चरण" निर्दिष्ट करना चाहते हैं। यदि आप बाहरी डेटा को मैन्युअल रूप से आवंटित करते हैं और 100% सुनिश्चित करते हैं कि यह निरंतर है, तो आप चरण पार नहीं कर सकते हैं और भरोसा नहीं कर सकते स्वत: कदम गणना।

मैं के साथ सी # परिचित नहीं हूँ, लेकिन यह मेरे लिए है कि आप सही ProcessImage कॉल के बाद डेटा जारी लगता है। तो अगर ProcessImage अतुल्यकालिक है या किसी भी तरह कैश अपने मैट्रिक्स (यानी मैट्रिक्स के जीवनकाल लंबा है टी टोपी प्रक्रिया इमेज कॉल), तो आपको स्मृति प्रबंधन की परवाह करनी चाहिए।

1

सी ++ कोड ठीक प्रतीत होता है, जिसमें यह आपूर्ति किए गए छवि डेटा के लिए मैट्रिक्स रैपर बनाता है, मानते हैं कि बफर पारंपरिक आरजीबी 8 प्रारूप में है। ध्यान दें कि यह कन्स्ट्रक्टर बफर की प्रतिलिपि करता है, इसलिए बफर को Mat इंस्टेंस (या कॉपी किया गया) की अवधि के लिए मान्य होना चाहिए।

Mat newImg = Mat(nImageHeight, nImageWidth, CV_8UC3, ptrImageData); 

ऐसा लगता है कि समस्या आपके सी # कोड में निहित है। मैं सी # डेवलपर नहीं हूं, लेकिन मैं मदद करने के लिए अपनी पूरी कोशिश करूंगा। आप मेमोरी स्ट्रीम बना रहे हैं और जेपीईजी कोडेक का उपयोग बफर में छवि के संपीड़ित संस्करण को लिखने के लिए करते हैं जैसे कि यह एक फ़ाइल थी।लेकिन डेटा प्रारूप जो cv::Mat डेटा प्रारूप है, इसलिए आप मूल रूप से कचरा देखेंगे (संपीड़ित डेटा असम्पीडित के रूप में व्याख्या किया जाएगा)।

System.Image.Drawing.Image उदाहरण दिया गया है, तो आप सीधे एक रैपर Bitmap ऑब्जेक्ट बना सकते हैं (या शायद as का उपयोग करें, क्योंकि यह एक साधारण डाउनकास्ट है)। फिर आप अंतर्निहित छवि डेटा में पॉइंटर प्राप्त करने के लिए Bitmap.LockBits() विधि tog का उपयोग कर सकते हैं।

Bitmap bmp = new Bitmap(sourceImage); 

// Lock the bitmap's bits. 
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 
System.Drawing.Imaging.BitmapData bmpData = 
    bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, 
    bmp.PixelFormat); 

// Get the address of the first line. 
IntPtr ptr = bmpData.Scan0; 

// Declare an array to hold the bytes of the bitmap. 
int bytes = Math.Abs(bmpData.Stride) * bmp.Height; 
byte[] rgbBuffer = new byte[bytes]; 

// Copy the RGB values into the array. 
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbBuffer, 0, bytes); 

// Do your OpenCV processing... 
// ... 

// Unlock the bits. 
bmp.UnlockBits(bmpData); 

और फिर आप rgbBuffer को ओपनसीवी में पास कर सकते हैं।

मुझे विश्वास नहीं है कि मूल कोड में मेमोरी प्रबंधन पूरी तरह से सही है, लेकिन फिर भी उपरोक्त काम करेगा बफर स्वामित्व का दायरा लॉक के भीतर है और विधि कॉल अनलॉक है। यदि छवि डेटा इस कोड ब्लॉक से बाहर निकलना है, तो आपको बफर की प्रतिलिपि बनाना होगा।

अपने पिक्सेल प्रारूपों से भी सावधान रहें - आपको यह सुनिश्चित करना होगा कि Image/Bitmap उदाहरण में वास्तव में RGB8 डेटा शामिल है। ओपनसीवी के cv::Mat में विभिन्न झंडे हैं ताकि आप विभिन्न प्रकार के मेमोरी छवि प्रारूपों के साथ काम कर सकें। लेकिन ध्यान दें कि ये ऑन-डिस्क (आमतौर पर संकुचित) प्रारूपों जैसे पीएनजी, टीआईएफएफ, और इसी तरह के समान हैं।

+0

यहां सुझाए गए जटिल रूपांतरण के बजाय 'srcImage.Save (ms, System.Drawing.Imaging.ImageFormat.Jpeg)' कॉल को बदलने के लिए पर्याप्त हो सकता है 'ImageFormat.Bmp'' – slawekwin