OpenCV打開的圖片在記憶體中如何與TBitmap相互轉換,以便用TImage顯示?
uj5u.com熱心網友回復:
不能轉換,自己根據 cv::Mat 中的資料填充一張位圖即可, 比如一個簡單的方法,cv::Mat(C++) 或者IplImage(C語言)中,直接獲取他的type,col,row,還有data屬性,然后delphi通過這些引數直接創建一個位圖填充像素即可。uj5u.com熱心網友回復:
是填充TBitmap的Pixels[x][y]嗎?可以把data轉成ScanLine嗎?
uj5u.com熱心網友回復:
data 是一個資料存盤區指標而已,怎么轉?你自己不填充沒別的辦法,而且C++還要注意 ,cv::Mat 如果定義成區域變數(不是new出來的),,data的記憶體是自動釋放的。uj5u.com熱心網友回復:
我說的轉的意思是包含資料復制,data的資料可以轉換成ScanLine嗎?
uj5u.com熱心網友回復:
應該是都可以的,首先影像格式最好用32位或者24位影像格式,CV是可以轉換的。其次ScanLine就是存盤的影像中一行行的資料,所以只要將CV只的資料,按行的方式(如第一行是指標開始位置,第二行是開始位置加上影像寬度*4或者3,以此回圈),復制到ScanLine就可以了。如果是FMX的話,可以用map、unmap的方式做,需要注意的一是影像是格式是否一致,否則要RB互換,二是坐標體系,bitmap好像是從左下開始的,VC好像是從左上吧,資料直接move就可以了。uj5u.com熱心網友回復:
CV的影像資料和ScanLine資料,R、G、B還是B、G、R順序是一致的嗎?每像素行影像資料末尾不知道有沒有對齊填充?
RB互換是什么意思?
uj5u.com熱心網友回復:
windows的bitmap好像是按BGRA的順序存放的,而有些技術規范是按RGBA方式存盤的,如果轉換的兩邊不同,就要把RB通道換一下,直白點就是把一個像素占用的四個位元組中的第一個和第三個換一下就可以了(是不是一樣的,,查下資料,或者運行看一下顏色對不對就知道了。)。關于對齊 ,,你使用32位模式,就沒有對齊 問題的。速度也快,訪問方式也簡單,就只是一個點比24位多一個位元組,uj5u.com熱心網友回復:
@lvjun 我瀏覽器出問題參考點不了了如何要RB互換,CV的影像資料就不能直接拷貝給ScanLine了?RB互換有函式嗎?
如果原來影像就是24位的,那要考慮對齊問題嗎?
uj5u.com熱心網友回復:
opencv里用imwrite寫到一個bitmap檔案再打開最簡單了。uj5u.com熱心網友回復:
@DelphiGuy 我瀏覽器出問題參考點不了了寫到檔案再打開,不如在記憶體中操作速度快~
uj5u.com熱心網友回復:
......一行資料,無非是一個個點的資料的組合,而一個點是3個或者4個位元組(24和32位RGB)的組合而已,所謂的互換,無非就是兩個位元組內容換一下就可以了。如果一定要到代碼,就是用pbyte或者pansichar對應到影像資料或者scanline,例如第一個點就j m := p[0]; p[0] := p[2]; p[2] := m;就可以了,24位是有對齊的問題,scanline好像是按4位元組對齊的吧。uj5u.com熱心網友回復:
@lvjun 我瀏覽器出問題參考點不了了比如24位影像,不知道有沒有實際的代碼?
uj5u.com熱心網友回復:
如果opencv中Mat的內部存盤結構可以和Tbitmap的內部存盤結構對等的話(假設如此),可以:Mat src = imread("xxx");
src.convertTo(src, 某種格式);
TBitmap *bmp = new TBitmap;
bmp->Width = src.cols;
bmp->Height = src.rows;
bmp->PixelFormat = 某種格式;
memcpy(bmp->ScanLine[0], src.ptr, src.cols * src.elemSize);
沒有測驗,可能需要cast某些型別,也可能需要回圈每次復制一行,因為不清楚Mat的內部存盤結構能否和BITMAP的每行像素位元組數對齊到32位匹配。
uj5u.com熱心網友回復:
原來你發在Delphi版,我還以為是CB版呢。uj5u.com熱心網友回復:
@DelphiGuy 我瀏覽器出問題參考點不了了Delphi版人氣好一些~
uj5u.com熱心網友回復:
還有人在關注這個問題嗎,同遇到這個問題啊轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/46019.html
上一篇:小白求助。
