1. 程式人生 > 實用技巧 >MFC VC++ 使用openCV + zbar 實現攝像頭掃碼二維碼並動態識別

MFC VC++ 使用openCV + zbar 實現攝像頭掃碼二維碼並動態識別

目標是實現類似掃一掃的功能

1.使用OpenCV獲取攝像頭的影象

2.再用opencv處理圖片,把一張圖片中的二維碼(或條形碼)部分剪下下來(這個沒實現)

3.用zbar識別剪下後的圖片

這裡只實現了while接收攝像頭圖片建立執行緒去識別,即每接收一個圖片就建立執行緒幹活,

幹完沒識別就自己結束,識別了就結束while,或超時了結束while

這裡會有一個建立多個執行緒的問題,但我把 strQRData 獨佔,測試沒有發現問題

這裡在筆記本上測試可以實現掃一掃的功能,但在效能差一點的windows平板電腦上太卡了,沒有實際使用的價值

把程式碼放上來吧

 1     BOOL xxxDlg::OnInitDialog()
    //這是放到init中的一段程式碼,目的是開啟對話方塊就開始掃碼

    //
這裡是實現把opencv的圖片顯示放到pic控制元件中 2 namedWindow("view", WINDOW_AUTOSIZE); 3 HWND hWnd = (HWND)cvGetWindowHandle("view"); 4 HWND hParent = ::GetParent(hWnd); 5 ::SetParent(hWnd, GetDlgItem(IDC_STA_Scanning)->m_hWnd); 6 GetDlgItem(IDC_STA_Scanning)->ShowWindow(SW_SHOW); 7 ::ShowWindow(hParent, SW_HIDE);
8 9 VideoCapture capture(0); 10 if (!capture.isOpened()) 11 { 12 MessageBox(_T("fail to open")); 13 EndDialog(IDCANCEL);//退出視窗 14 return FALSE; 15 } 16 Mat frame; 17 Mat imageGray; 18 hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);// 建立訊號量物件 19 int
i_timeCount = 0;//20秒 20 while (b_scanning && (strQrData.IsEmpty()) && (i_timeCount < 20000)) 21 { 22 capture >> frame; 23 if (frame.data) 24 { 25 cvtColor(frame, imageGray, CV_RGB2GRAY); 26 AfxBeginThread(ThreadScanning, &imageGray, 0, 0, 0); 27 imshow("view", frame); 28 i_timeCount += 60;//這個時間控制差距比較大,需要根據實際機器的測試來確定20秒 29 waitKey(30); 30 } 31 else 32 { 33 b_scanning = FALSE; 34 } 35 } 36 if (strQrData.IsEmpty()) 37 { 38 MessageBox(_T("識別失敗,請重新識別或手動輸入")); 39 } 40 else 41 { 42 MessageBox(strQrData); 43 } 44 strQrData.Empty(); 45 b_scanning = TRUE; 46 EndDialog(IDCANCEL);//退出視窗 47 return TRUE; // return TRUE unless you set the focus to a control 48 //執行緒函式 49 50 BOOL b_scanning = TRUE; 51 CString strQrData; 52 HANDLE hSemaphore;//訊號量物件控制代碼 53 54 55 UINT ThreadScanning(LPVOID pParam) 56 { //執行緒要呼叫的函式 57   Mat *frame = (Mat *)pParam; 58   string ret; 59   ret = QRCode::GetQR(*frame); 60   if (!ret.empty()) 61   { 62     WaitForSingleObject(hSemaphore, INFINITE);// 試圖進入訊號量關口 63     b_scanning = FALSE; 64     strQrData = ret.c_str(); 65     ReleaseSemaphore(hSemaphore, 1, NULL);// 釋放訊號量計數 66   } 67   return 0; 68 }

這裡還要優化的地方

1. 識別圖片中二維碼和條形碼的區域,擷取後再識別二維碼的資料,這樣處理圖片會更快

2. 在while的迴圈中,設執行程式碼時間是codeTime,等待的時間是waitTime

現在程式碼的執行一輪迴圈的時間是codeTime + waitTime,而不是在等待時間中執行程式碼