none
C#開一個以上指標 RRS feed

  • 問題

  • 我在C#中用自製的DLL將bmp圖片轉為IplImage經過處理再轉回Bmp

    而在調整大小,或是擷取部分圖片時,圖片好像會沒傳回來,顯示的依然是位處理過的圖片

    在測試時發現位址好像不太對,找資料時也發現此篇http://sculptor9.pixnet.net/blog/post/42489880

    請問造成指標亂址的原因為和?

    該往什麼方向能解決?

    此篇說的一次開一個不太懂意思,就一直使用同一個IntPtr,收到就放到IntPtr陣列嗎? 目前測試是失敗的...

    我的程式單純在c++中執行沒問題,所以應該是在C#方面吧?

     

    2011年8月22日 上午 08:48

解答

所有回覆

  • 指標沒有亂指,而是你沒有更新 C# 中的指標變數吧 ...
    小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
    雲端學堂Facebook: http://www.facebook.com/studyazure
    2011年8月22日 上午 09:32
    版主
  • 更新是指...假如方法A和B都會回傳一個指標

    IntPtr a= A(XXX);

    使用後再

     a=B(XXX);

    這樣算更新嗎?

    2011年8月23日 上午 03:18
  • 你用除錯器去觀察 A(xxx) 和 B(xxx) 給予的值不就知道有沒有更新了...
    小朱的技術隨手寫:http://www.dotblogs.com.tw/regionbbs/
    雲端學堂Facebook: http://www.facebook.com/studyazure
    2011年8月23日 上午 03:41
    版主
  • 這樣的動作是將a指標指向B函數傳回的位址, 沒有更動a指標指到的記憶體的內容
    2011年8月23日 上午 05:54
  • 我寫了一個函式在C#來顯使IplImage,證明我的確有成功才對

     

     Ipl = BmpToIpl(...........); //確定有轉成功  Ipl此時為IplImage格式檔

    這邊做處理、畫圓、畫線、擷取圖片區域部分皆成功

    IplToBMP(Ipl, 緩衝區); //轉回BMP

    顯示在pictureBox

    畫圓、畫線可以成功的顯示,可是擷取圖片的化,沒任何效果,感覺像是顯示未處理前的圖。但既然Ipl的確有變,做別的功能又能成功執行,代表轉回Bmp方法也沒問題才對。

    想到的可能是,畫直線或圓,試用偵測到的數據直接在原圖畫並回傳,而擷取或長寬調整則須再創造IplImage,會不會是那個時候跑掉的??

    以下為我DLL中擷取部分圖片並放大的程式碼

    IplImage*  reROI(IplImage*image)

    {

     CvRect Rect1 =cvRect(110,110,200,200);//cvRect(x,y,w,h)

     cvSetImageROI(image,Rect1);

     IplImage * reimage = cvCloneImage(image);

     image = cvCreateImage(cvSize(寬, 高) ,image->depth ,image->nChannels);

     

     //特別將image初始化是想說降位址就不會動到,但看來好像不對...

     cvResize(reimage ,image ,1);

     

           return image; 

    }

    正常是直接

     

    IplImage * reimage = cvCreateImage(cvSize(,) ,image->depth ,image->nChannels);

    cvResize(image , reimage,1);  

    return image;

     

     


    2011年8月23日 上午 09:19
  • 您的函數會將參考做處理, 再傳回參數的值, 乾脆不要回傳了, 直接將參考指標指到內容值改掉即可

    IplImage*  reROI(IplImage*image)

    {

           return image; 

    }

    2011年8月24日 上午 05:45
  • to tihs:不是很懂你的意思, 但我嘗試過若不回傳的話,我C#這邊的圖不能做二次的變動,會產生錯誤

    void reROI(IplImage*image)

    {

     

     CvRect Rect1 =cvRect(110,110,200,200);//cvRect(x,y,w,h)

     cvSetImageROI(image,Rect1);

    IplImage * reimage = cvCreateImage(cvSize(,) ,image->depth ,image->nChannels);

    cvResize(image , reimage,1);  

    }

    若用OpenCV的視窗顯示出來,是有成功的

    但是在IplToBMP(Ipl, 緩衝區); //轉回BMP 這邊好像沒反應,因為它顯示還是全圖

    我不知道是因為我有動到圖的大小而讓轉bmp失敗還是因為有創造新的IplImage*讓指標跑掉

    當然這兩個原因是我自己目前覺得錯誤的原因,還在嘗試...


    • 已編輯 TSWAL 2011年8月24日 下午 12:24
    2011年8月24日 上午 08:21
  • void cvResize(const CvArr* src, CvArr* dst, int interpolation=CV INTER LINEAR );

    cvResize 完後, resize 的圖片是在 dst 裡對吧, 也就是你的 reimage 對吧

    那你 return image; 這句是回文打錯, 還是程式碼真的寫錯.......... 是 return reimage 嗎??

    不過既然有 return 的話, 你的函式宣告也怪怪的

    void reROI(IplImage*image) 應該是

    IplImage* reROI(IplImage*image) 嗎 ??

    註 : 你上下回文貼的都不一樣.......那一份是有問題的 code 阿
    2011年8月24日 上午 11:12
  • to Apple I:抱歉,回復貼太快,照理說兩份程式碼都沒問題才對。在C++執行都沒錯

    但...在C#中則會有點問題

     Ipl = BmpToIpl(...........); //確定有轉成功  Ipl此時為IplImage格式檔

    這邊做處理、畫圓、畫線、擷取圖片區域部分皆成功(有用cvShowImage顯示出來看過)

    IplToBMP(Ipl, 緩衝區); //轉回BMP

    顯示在pictureBox

    顯示在pictureBox的部分,畫圓畫線都可以,但擷取則會沒顯示在上面,顯示的一樣是全圖

    2011年8月24日 下午 12:28
  • 來討論一下 ROI 吧

    ROI 是在 IplImage 做一個區域. 然後其他 OpenCV 函式處理這個 IplImage 結構時, 會只處理 ROI 的部分 (如果 ROI 不為 NULL 的話). 因為沒有看到 IplToBMP() 的碼, 我假設你認為 set ROI 後, 會只轉換 ROI 的部份, 但結果看來是整個 IplImage 都轉成 BMP, 因此你才會一直看到都沒有 "擷取" 的效果

    感覺起來你要做 crop 試試這樣吧

    crop = cvCreateImage(size=ROI...)
    cvSetImageROI(image,....)
    cvCopy(image, crop)
    return crop

    用 cvCopy 而不用 cvCloneImage. 是因為 copy 是複製出一個新的 array. 而 clone 是複製整個 IplImage, 所以用 clone 你還是在處理整個 IplImage, 而不是變成你選的 ROI 範圍.

    如果這是你的問題癥結點的話, 記得回文說有沒有效.........

    2011年8月24日 下午 03:42
  • to Apple I :  cvCopy與 cvCloneImage的差異我的確不知道,謝ˋ謝你的說明。

    但我還是沒有成功在pictureBox上顯示址擷取的區域

    IplImage*  reROI(IplImage* image,int x,int y,int width,int height ){

            CvRect Rect1 =cvRect(x,y,width,height);

    cvSetImageROI(image,Rect1); //擷取

    IplImage *Csize = cvCreateImage(cvSize(width,height) ,image->depth ,image->nChannels);

    cvCopy(image ,Csize );//先複製擷取的部分,然後下面再轉大小

    IplImage * reimage= cvCreateImage(cvSize(1280,1024) ,image->depth ,image->nChannels);

    cvResize(Csize ,reimage , 1);//因為我顯示部分是以1280*1024,轉完大小後回傳

          return reimage;
    }
    請問我上面的程式碼中有任何問題嗎? (至少在c++中測試是成功的...)
    另外我IplToBmp是參考以下這個網頁中的"從IPLIMAGE對像中生成BMP的圖像文件流"
    只是有把size改掉不用而已

    2011年8月25日 上午 02:11
  • 是否是因為畫圓和畫線都是畫在原圖上, 而擷取則不是, 您可以嘗試將擷取到的圖取代原圖, 看看是否可以成功?
    2011年8月25日 上午 02:32
  • 我發現了一個問題

     Ipl = BmpToIpl(...........); //用來將BMP格式轉為IplImage,詳細參考以下

    http://opencvinvs.blogspot.com/2011/08/iplimage-to-bmp.html

    那照理說,我IplImage格式的資料應該都存在image所指的位址吧,結果現在好像是存在我原本放Bmp資料那邊。所以其實我處理完,不需要IplToBMP,直接用去抓原位置(BMP的)的資料就已經是有處理過的資料影像了(偵測圓,直線),請問關於這邊是怎麼回是呢?

    另外...看來我轉回BMP那邊是失敗的(IplToBmp(Ipl, 緩衝區); ),我跟範例中程式碼不同處在於我把size注解掉了,因為我緩衝區的大小已經知道了,想說用不到size。還是說那個size其實還有別的重要意義??

     



    2011年8月25日 上午 06:57
  • 自行測試後,發現使用SetData會參考同一個位址(應該是這樣講吧)

    所以不管對原圖,或是我以為新創造出來的Ipl圖做改變,兩個圖皆會改變


    2011年8月26日 上午 01:45
  • 如果兩個圖都會改變代表是同一個, 那就更不需要將處理過的結果傳回了

    2011年8月26日 上午 02:44
  • 我在C#中用自製的DLL將bmp圖片轉為IplImage經過處理再轉回Bmp

    可不可以請你詳細一下說明你在 C# 裡 怎麼引用呼叫  opencv 的函式, 及為何要 bmp-> Iplimage -> bmp 呢 ??

    可以直接給檔名開起 Iplimage 然後 to bmp 嗎 ?? 還有就是如果只是要在 .net 裡用 opencv 有考慮 emgu cv 嗎 ??

    希望你能詳細點說說, 我想要試試看會不會遇到跟你一樣的問題. TKS~

    還有關於 SetData, 只是把 raw data 放進有初始 Iplimage header 的 array 裡吧.

    cvSetData
    Assigns user data to the array header.

    希望你有懂我寫的, 因為我看不太懂你最後 po 的意思......

    2011年8月26日 上午 10:34
  • OpenCV函式我都是在自製的DLL(c++)中去使用,C#與C++之間傳遞主要是傳圖片(指標?)(IntPtr、IplImage*)

    程式為從攝影機讀取到畫面放置暫存區(raw data),然後將之轉為IplImage型態去做處理。處理完後再轉為BMP,但發現根本不用轉為BMP(轉回BMP那行就沒在使用),原因可能如上所講,是因為他們使用到的資料是同一個位置的。這可能還需要多測試

    SetData測試時我先讀取一個圖片,然後再IplImage *image,接著設定cvInitImageHeader,使用SetData。然後我在其一張圖畫線,發現兩張圖皆會畫過線

    以下是測試程式碼,可以拿這試試,或是看看有無錯誤。

    http://opencvinvs.blogspot.com/2011/08/cvsetdata.html

    2011年8月29日 上午 01:27
  • 1.你的 cvSetData 的疑問, 看一下源碼在 src\cxcore\cxarray.cpp 裡應該就瞭解了

    cvSetData( CvArr* arr, void* data, int step ), 如果來源 arr 是一個 Iplimage,

    則 cvSetData 只是做 img->imageData = img->imageDataOrigin = (char*)data;

    所以都是同一個位址的東東吧, 只不過 img 是一個有 Iplimage header 的指標

    2.至於 up side down 的問題 Iplimage 裡有個

    origin : 0 - top-left origin, 1 - bottom-left origin (Windows bitmap style)

    所以應該是 bitmap 的問題吧

    3.還有你用 IplImage *img =new IplImage; 再  cvInitImageHeader()

    看一下源碼 : cvCreateImage() 會呼叫 cvCreateImageHeader() ,

    cvCreateImageHeader() 內部會 alloc 一個 Iplimage, 再呼叫 cvInitImageHeader()

    所以其實你可以只用 cvCreateImage() 或 cvCreateImageHeader() 就行了

    互相研究吧~ 有誤懇請各位大大指教~

     

    2011年8月29日 上午 08:27
  • 跟這篇類似嗎?

    [Net] WinForm 中 PictureBox 的圖層

    因為在不同圖層,你混用了 GDI 函數與 .Net 方法。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2011年8月29日 上午 09:32
  • 這幾天不舒服沒上限...沒想到已經有版主幫我標示最佳解答了@@

    to Apple I:謝謝你的指導喔,有人可以請教真的獲益良多

    to 心冷熱情息:謝謝你提供的資料,以參考到


    2011年9月4日 下午 04:36