小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

如何使用GDI或者GDI+的函數(shù)對IplImage進(jìn)行圖像處理?

 學(xué)海無涯GL 2013-05-05
如何將OpenCV中的IplImage顯示在MFC的窗口中

:主要函數(shù)有兩個(gè),一個(gè)是填寫相應(yīng)的Bitmapinfo結(jié)構(gòu)體,另外一個(gè)是把圖片顯示到CWnd類型的窗口上去。
 雖然我特殊處理了一下256位的圖,但我仍然無法畫灰度圖,挺奇怪的。目前只支持24位的圖片。
main:
IplImage *img = cvLoadImage("****");
BITMAPINFO bmi;
FillBitmapInfo(&bmi, img->width, img->height, img->depth*img->nChannels);
ShowImage(img, wnd, bmi); // 這里的wnd是目標(biāo)窗口,必須是CWnd類型的。
 
void FillBitmapInfo( BITMAPINFO *bmi, int width, int height, int bpp )
{
 ASSERT( bmi && width > 0 && height > 0 &&
  (bpp == 8 || bpp == 24 || bpp == 32) );
 BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
 memset( bmih, 0, sizeof(*bmih));
 bmih->biSize   = sizeof(BITMAPINFOHEADER);
 bmih->biWidth  = width;
 bmih->biHeight = -abs(height);
 bmih->biPlanes = 1;
 bmih->biBitCount = bpp;
 bmih->biCompression = BI_RGB;
 if( bpp == 8 )
 {
  RGBQUAD* palette = bmi->bmiColors;
  int i;
  for( i = 0; i < 256; i++ )
  {
   palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
   palette[i].rgbReserved = 0;
  }
 }
}
void ShowImage(IplImage *pImg, CWnd *wnd, BITMAPINFO &bmi)
{
 CDC *pDC = wnd->GetDC();
 HDC  hDC = pDC->GetSafeHdc();
 CRect rect;
 wnd->GetClientRect(&rect);
 if(bmi.bmiHeader.biBitCount== 8)
 {
  CPalette pal;
  HPALETTE hpal=NULL;
  HPALETTE hOldPal=NULL;
  ::SetPaletteEntries(hpal,0,256,(LPPALETTEENTRY)bmi.bmiColors);
  hOldPal = ::SelectPalette(pDC->GetSafeHdc(), hpal, TRUE);
 }
 ::SetStretchBltMode(pDC->m_hDC, COLORONCOLOR);
 ::StretchDIBits(pDC->GetSafeHdc(),rect.left,rect.top,pImg->width,pImg->height,0,0,
    pImg->width,pImg->height,pImg->imageData,&bmi,DIB_RGB_COLORS,SRCCOPY);
}



(1 )IplImage -> Bitmap and Bitmap -> IplImage

IplImage *img ;
Bitmap bitmap( 20 ,20 ,PixelFormat24bppRGB ) ;
Graphics pGra( & bitmap) ;
HDC hdc = pGra ->GetHDC() ;
CvvImage cvimg ;
cvimg .CopyOf( img , -1) ;
RECT rect = { 0 , 0 , img ->width , img ->height } ;
cvimg.DrawToHDC( hdc , &rect ) ;
pGra ->ReleaseHDC( hdc ) ;

IplImage *tempimg = cvCreateImage(cvSize(bitmpa ->GetWidth() , bitmap ->Getheight (), 8 , 3) ;
BitmapData mydata;
Rect rect(0, 0, bitmpa ->GetWidth() , bitmap ->Getheight()) ;
bitmap.LockBits( &rect , ImageLockModeRead , PixelFormat24bppRGB ,&mydata) ;
memcpy(tempimg ->imagedata, mydata.scan0 , tempimg->width * tempimg->height* 3) ;
bitmap.UnlockBits( & objdata ) ;


(2) CBitmap ->Bitmap adn Bitmap -> CBitamp

CDC *pdc = this ->GetDC() ;
CBitmap m_Cbit;
m_Cbit.CreateCompatibleBitmap(pdc , 100 ,100 ) ;
Bitmap m_bit((HBITMAP) m_Cbit , NULL) ;

HBITMAP bitmap ;
m_bit.GetHBITMAP( Color( 0 , 0 , 0) , & bitmap ) ;
CBitmap *m_pbit = CBitmap ::FromHandle( bitmap) ;

...do something ;

m_pbit->DeleteObject() ;

(3) IplImage ->CBitmap , Cbitmap ->IplImage
CDC *pdc = this ->GetDC() ;
IplImage *img = cvCreateImage( cvSize( 100,100 ) , 8 , 3 );
CBitmap m_bitmap ;
m_bitmap.CreateCompatibleBitmap( pdc , 100 ,100 ) ;
CDC memdc ;
memdc.CreateCompatibleDC( pdc ) ;
CBitmap *pold = memdc .SelectObject( &m_bitmap) ;
CvvImage cvimg ;
Rect rect(0 , 0 , 100,100 ) ;
cvimg.CopyOf( img , -1 ) ;
cvimg.DrawToHDC( memdc.m_hDC , &rect ) ;
ReleaseDC( pdc) ;
IplImage *tempimg = cvCloneImage( img ) ;
m_bitmap.GetBitmapBits( img ->widthStep * img ->height , img ->imageData) ;

DirectShow OpenCV GDI+ 圖形顯示格式轉(zhuǎn)換

DirectShow OpenCV GDI+ 圖形顯示格式轉(zhuǎn)換

GDI+在顯示圖像方面要比GDI使用起來更方便

OpenCV圖像處理方面無論深度和與VC的兼容性方面都是很好的,
DirectShow要視頻采集方面目前應(yīng)該說是最優(yōu)秀的

但OpenCV的IplImage格式與GDI+所需要的BITMAPINFO稍有不同
同時(shí)OpenCV集成的視頻捕捉部分采用的VFW,效率上遠(yuǎn)不如DirectShow

三者之間的圖像轉(zhuǎn)換工作我采用的如下方法,經(jīng)測試效率還可以
測試架構(gòu)為
1.DirectShow采集一幀圖像到源內(nèi)存buf,把此buf轉(zhuǎn)為OpenCV的彩色I(xiàn)plImage格式
2.用OpenCV的方法轉(zhuǎn)成灰度圖得到一個(gè)新的灰度IplImage
3.把灰度IplImage轉(zhuǎn)為GDI+所能識別的Bitmap,顯示到指定DC中
以上所有過程沒有對源內(nèi)存buf的無效copy過程(當(dāng)然轉(zhuǎn)灰度圖過程OpenCV是要建個(gè)Buf的,不可省的)

1.DirectShow采集一幀圖像到源內(nèi)存buf,在CB函數(shù)中..
STDMETHODIMP CSampleGrabberCB::BufferCB(double SampleTime, BYTE * pBuffer, long BufferSize )
{

//cvCreateImage opencv自帶函數(shù),建立一個(gè)空圖

IplImage *pImg = cvCreateImage(cvSize(biWidth ,biHeight), 8, 3);//建立空圖3*8=24位

pImg->imageData = (char*)pBuffer;//得到buf指針,圖像創(chuàng)建完畢

::SendMessageW(m_hWnd, UM_DVBACK, 0, LPARAM(pImg));//把圖發(fā)到主線程,轉(zhuǎn)2

cvReleaseImage(&pImg);//釋放圖

return 0;

}

2.在主線程中消息響應(yīng)函數(shù)中用OpenCV的方法轉(zhuǎn)成灰度圖得到一個(gè)新的灰度IplImage
LRESULT CMy05_ThreadSnapDlg::OnUMDVBACK(WPARAM wParam, LPARAM lParam)
{

IplImage *pImgSrc = (IplImage *)lParam;// 得到源圖

IplImage* pImgGray = cvCreateImage(cvGetSize(pImgSrc), 8, 1);// 建立新的空的灰度圖

cvCvtColor(pImgSrc, pImgGray, CV_BGR2GRAY);// 24位RGB彩圖轉(zhuǎn)灰度圖,opencv自帶函數(shù),這里可以使用任何opencv函數(shù)進(jìn)行圖象處理

DrawImgToHwnd(m_hWnd, pImgGray); //自寫函數(shù),顯示灰度圖,即處理結(jié)果;轉(zhuǎn)3

}

3.把灰度IplImage轉(zhuǎn)為GDI+所能識別的Bitmap,顯示到指定DC中
void CMy05_ThreadSnapDlg::DrawImgToHwnd(HWND hWnd, IplImage *pImg)
{

int nBitCount = (pImg->depth & 255) * pImg->nChannels;//圖像色彩深度 opencv源碼這樣寫的,也可以直接乘

int nWidth = pImg->width;

int nHeight = pImg->height;//這里特別注意,如果發(fā)現(xiàn)倒像,這里設(shè)為負(fù)值即可(-pImg->height)

BITMAPINFO *pBITMAPINFO = nBitCount == 24 ? m_pBITMAPINFO_24:m_pBITMAPINFO_08;

//24位圖和8位圖的BITMAPINFO是固定的,要提前創(chuàng)建好,一次即可

Bitmap* pBitmap = Bitmap::FromBITMAPINFO(pBITMAPINFO, pImg->imageData);//GDI+的圖像格式

Graphics *gdiDC = Graphics::FromHWND(hWnd);//GDI+創(chuàng)建畫板方法

gdiDC->DrawImage(pBitmap,0,0);//GDI+畫圖方法

delete pBitmap;

delete gdiDC;

}


使用GDI+顯示OpenCV中的圖像IplImage

  OpenCV雖然自帶了輕量級的界面庫HighGUI,但是支持的圖像化元素實(shí)在是太少了,一般只在前期算法測試時(shí)使用。實(shí)際產(chǎn)品還是使用MFC庫。因此本文記錄了如何在GDI+中顯示OpenCV中的IplImage格式的圖像數(shù)據(jù)。

  假設(shè)創(chuàng)建的MFC MDI應(yīng)用程序名為GdiplusTest。關(guān)于如何在MFC中使用GDI+圖形化系統(tǒng)已經(jīng)在《GDI+ 使用指南》一文中介紹了。

  顯示OpenCV中的IplImage圖像格式具體步驟如下:

  1. 在GdiplusTestView.cpp中添加OpenCV的頭文件
    #include <cv.h>
    #include <highgui.h>
  2. 在CGdiplusTestView::OnDraw(CDC* pDC)函數(shù)中添加如下代碼:
    復(fù)制代碼
    //載入圖像
    IplImage* srcImage = cvLoadImage("lena.jpg");
    //創(chuàng)建Bitmap對象
    Gdiplus::Bitmap bitmap(srcImage->width, srcImage->height, srcImage->widthStep,
    PixelFormat24bppRGB, (BYTE*)srcImage->imageData);

    Gdiplus::Graphics graphics(pDC->GetSafeHdc());
    graphics.DrawImage(&bitmap, 0, 0);

    GDI+ 使用指南(basic guiding of GDI plus )

      其實(shí)這個(gè)也沒有什么用,畢竟已經(jīng)是過時(shí)的技術(shù)了。不過技術(shù)的更新跟實(shí)際的使用還是有差距了,免不了還是要用這種過時(shí)的技術(shù),所以還是記錄下來,方便以后查閱。
      GDI+沒記錯(cuò)的話是跟隨XP誕生的,是XP系統(tǒng)上的圖形繪制系統(tǒng)(以前的是GDI),GDI+相對于GDI提供了一些新的特性,比如漸變的畫刷,支持多種圖像格式等等。不過我覺得最大的變化,還是編程模型上的變化。GDI+使用了面向?qū)ο蟮乃枷耄瑢涌谶M(jìn)行了類封裝,使用更加方便。
      在應(yīng)用程序中使用GDI+庫應(yīng)該遵循一下步驟:
      1.包含Gdiplus.h頭文件,如果圖方便,加上:using namespace Gdiplus;這樣使用GDI+中的任何東西就不需要重新指定命名空間了。
      2.鏈接DLL的導(dǎo)入庫Gdiplus.lib。在VS中有兩種方法,一是直接在項(xiàng)目屬性->鏈接->輸入中填入Gdiplus.lib;二是直接使用編譯器原語:#pragma comment(lib, "Gdiplus.lib")
      3.在調(diào)用任何GDI+函數(shù)前一定要調(diào)用GDI+庫初始化函數(shù)GdiplusStartup(),初始化GDI+庫。
      4.在確定不需要使用任何GDI+函數(shù)并且所有GDI+對象均已銷毀(變量超過了生存期),需要調(diào)用GDI+關(guān)閉函數(shù)GdiplusShutdown()。GDI+支持多線程,所以可以在任意一個(gè)線程中調(diào)用。

      下面講下在實(shí)際MFC 單/多文檔程序中,如何使用GDI+圖形系統(tǒng)(程序名叫:GdiplusTest)。
      1.在Stdafx.h頭文件中添加如下代碼

    #include <GdiPlus.h>
    #pragma comment(lib, "Gdiplus.lib")

      2.在CGdiplusTestApp類中,添加兩個(gè)變量,用于GDI+初始化函數(shù)。

    private:
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;

    3.在CGdiplusTestApp::InitInstance()函數(shù)中添加如下代碼,一定要在pMainFrame->ShowWindow(m_nCmdShow)之前,建議添加在CWinAppEx::InitInstance()之后。

    // Initialize GDI+.
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    4.重載CGdiplusTestApp的ExitInstance()函數(shù),然后添加GDI+關(guān)閉函數(shù)。

    	Gdiplus::GdiplusShutdown(gdiplusToken);

    5.在CGdiplusTestView::OnDraw(CDC* pDC)函數(shù)中使用GDI+類,顯示圖片lena.jpg

    Gdiplus::Graphics graphics(pDC->GetSafeHdc());
    Gdiplus::Image image(L"lena.jpg");
    graphics.DrawImage(&image, 10, 10);

    
    

    OpenCV ---HBITMAP to IplImage

    IplImage* hBitmap2Ipl(HBITMAP hBmp)
    {

    BITMAP bmp;
    ::GetObject(hBmp,sizeof(BITMAP),&bmp);
    int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
    int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
    IplImage* img = cvCreateImageHeader( cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels );
    img->imageData =(char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char));
    memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels);
    return img;
    }

    void createDIB(IplImage* &pict)

    {

    IplImage * Red=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U, 1 );
    IplImage * Green=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U, 1 );
    IplImage * Blue=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),IPL_DEPTH_8U, 1 );
    cvSetImageCOI( pict, 3);
    cvCopy(pict,Red);
    cvSetImageCOI( pict, 2);
    cvCopy(pict,Green);
    cvSetImageCOI(pict, 1);
    cvCopy(pict,Blue);
    //Initialize the BMP display buffer
    bmi = (BITMAPINFO*)buffer;
    bmih = &(bmi->bmiHeader);
    memset( bmih, 0, sizeof(*bmih));
    bmih->biSize = sizeof(BITMAPINFOHEADER);
    bmih->biWidth = IMAGE_WIDTH;
    bmih->biHeight = IMAGE_HEIGHT; //
    -IMAGE_HEIGHT;
    bmih->biPlanes = 1;
    bmih->biCompression = BI_RGB;
    bmih->biBitCount = 24;
    palette = bmi->bmiColors;
    for( int i = 0; i < 256; i++ ){
    palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed =(BYTE)i;
    palette[i].rgbReserved = 0;
    }
    cvReleaseImage(&Red);
    cvReleaseImage(&Green);
    cvReleaseImage(&Blue);
    }


    IplImage與CImage 圖像類型的轉(zhuǎn)換

    IplImage* plmg; //定義兩個(gè)IplImage和CImage類型
    CImage cimg;
    plmg=cvLoadImage(pDoc->m_paName,1); //然后以路徑為參數(shù),把圖形讀進(jìn)IplImage cimg.CopyOf(plmg); //把IplImage轉(zhuǎn)換成CImage類型

    pImg =cimg.GetImage(); //把CImage類型轉(zhuǎn)換成IplImage

    CRect rect(0,0,cimg.Width(),cimg.Height());
    HDC hDC=pDC->GetSafeHdc();
    cimg.DrawToHDC(hDC,rect); //CImage類型才能用DrawToHDC進(jìn)行顯示

    Bitmap與IplImage之間的轉(zhuǎn)換

    在MFC編程中,用OpenCV來處理圖像時(shí),可能會進(jìn)行Bitmap與IplImage之間的轉(zhuǎn)換;所以在此留個(gè)記號,以免下次再用到的時(shí)候,還要去找。

    IplImage* BitmapToIplImage(HBITMAP hBmp)
    {
    	BITMAP bmp;    
    	
    	GetObject(hBmp, sizeof(BITMAP), &bmp);
    	int depth     = (bmp.bmBitsPixel == 1) ? IPL_DEPTH_1U : IPL_DEPTH_8U;
    	int nChannels = (bmp.bmBitsPixel == 1) ? 1 : bmp.bmBitsPixel/8;    
    	
    	IplImage* img = cvCreateImage(cvSize(bmp.bmWidth,bmp.bmHeight), depth, nChannels);  
    	
    	BYTE *pBuffer = new BYTE[bmp.bmHeight*bmp.bmWidth*nChannels];    
    	GetBitmapBits(hBmp, bmp.bmHeight*bmp.bmWidth*nChannels, pBuffer);
    	memcpy(img->imageData, pBuffer, bmp.bmHeight*bmp.bmWidth*nChannels);   
    	delete pBuffer;
    
    	IplImage *dst = cvCreateImage(cvGetSize(img), img->depth,3);    
    	cvCvtColor(img, dst, CV_BGRA2BGR);   
    	cvReleaseImage(&img);   
    	return dst;
    }

    如果要從CBitmap轉(zhuǎn)為IplImage,可以先將CBitmap轉(zhuǎn)為BITMAP,再由BITMAP轉(zhuǎn)為IplImage;

    // CBitmap 轉(zhuǎn)為 BITMAP
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP);
    BITMAP   bmp;
    bitmap.GetBitmap(&bmp);
    
    // CBitmap與HBITMAP間的轉(zhuǎn)換
    // CBitmap轉(zhuǎn)為HBITMAP
    CBitmap bitmap;
    bitmap.LoadBitmap(IDB_BITMAP);
    HBITMAP bmp = HBITMAP(bitmap);
    // HBITMAP轉(zhuǎn)為CBitmap
    HBITMAP  hbitmap;  
    CBitmap   bitmap;
    bitmap.Attach(hbitmap);
    

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多