MFC调用摄像头拍照,通过curl把图片传给java后台
来源:互联网 发布:世界国家省市区数据库 编辑:程序博客网 时间:2024/06/05 10:56
接着上一篇博客的背景。
现在需要实现的功能是,在前端MFC上进行拍照并显示,之后把图片传给后台。
首先第一个部分是拍照的实现,通过百度,发现大家都是在使用opencv这个插件,容易实现。
(一)VS2010配置openCV(这个配置好麻烦)
参考的链接: http://johnhany.net/2013/11/environment-for-opencv-with-vs2010/
(1)下载安装openCV
下载到的文件名为“opencv-2.4.9.exe”,是个自解压文件,大小350MB左右.官网或者我发的链接 (资源统一在后面)
下载好之后,解压到任意一个文件夹,比如“E:\softwares”
(2)环境变量的配置
OpenCV库函数需要通过用户环境变量调用所需要的库文件。点击:开始->计算机(右击)->属性->高级系统设置->高级->环境 变量,在用户变量里增加一项:
变量名:path
变量值:E:\softwares\opencv\build\x86\vc10\bin
如果已经有path项,在其变量值结尾添加英文分号“;”,再加上上面那个值。
这里的“x86”代表目标程序是32位的,如果要写64位的程序则选择“x64”文件夹。并不是根据开发环境(你的机器)选择的。
后面的“vc10”代表使用Visual C++ 2010开发。如果使用Visual Studio 2012,则填写“E:\softwares\opencv\build\x86\vc11\bin”。
注销用户,重新登录Windows,保证环境变量更新并起作用。
(3)在VS2010中配置
在Solution Explorer中右击工程名,选择Properties。
在弹出的窗口“OpencvTest Property Pages”中,Configuration选择“Debug”(或者默认的“Active(Debug)”),Platform选择“Win32”。在左边选择Configuration Properties->VC++ Directories,在右边的General中编辑Include Directories,增加以下三项:
E:\softwares\opencv\build\include
E:\softwares\opencv\build\include\opencv
E:\softwares\opencv\build\include\opencv2
其实只需要填入第一行即可。由于“include\opencv”包含C版本的头文件,“include\opencv2”包含C++版本的头文件。所以编写代码时,在头文件名称前加上“opencv/”或“opencv2/”来区分两种版本。
在Library Directories中增加以下一项:
E:\softwares\opencv\build\x86\vc10\lib
把Configuration改为“Release”,然后对Include Directories和Library Directories做同样的修改。如果只写练习程序,只用debug功能,那么“Release”可以不用修改。如果使用Visual Studio 2012,则填写“E:\softwares\opencv\build\x86\vc11\lib”。
仍然在“OpencvTest Property Pages”窗口下,Configuration选择“Debug”。在左边选择Configuration Properites->Linker->Input,在右面编辑Additional Dependencies,增加以下若干项(可以根据自己的需要适当删减,关于各个模块的功能,请参考这里):
opencv_calib3d249d.lib
opencv_contrib249d.lib
opencv_core249d.lib
opencv_features2d249d.lib
opencv_flann249d.lib
opencv_gpu249d.lib
opencv_highgui249d.lib
opencv_imgproc249d.lib
opencv_legacy249d.lib
opencv_ml249d.lib
opencv_objdetect249d.lib
opencv_ts249d.lib
opencv_video249d.lib
(同样,如果仅使用debug模式,这一步可以跳过)把Configuration改为“Release”,在Additional Dependencies增加以下若干项(在文件名上的区别仅在于在末尾少了一个“d”):
opencv_calib3d249.lib
opencv_contrib249.lib
opencv_core249.lib
opencv_features2d249.lib
opencv_flann249.lib
opencv_gpu249.lib
opencv_highgui249.lib
opencv_imgproc249.lib
opencv_legacy249.lib
opencv_ml249.lib
opencv_objdetect249.lib
opencv_ts249.lib
opencv_video249.lib
至此 opencv配置好了,可以使用了。
(二)实现拍照功能
(三)图片显示
int http_post_file(const char *url, const char *filename){ CURL *curl = NULL; CURLcode res; struct curl_httppost *post=NULL; struct curl_httppost *last=NULL; struct curl_slist *headerlist=NULL; static const char buf[] = "Expect:"; if(filename == NULL || url == NULL) return -1; printf("URL: %s\n", url); printf("filename: %s\n", filename); /* Add simple file section */ if( curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filename, CURLFORM_END) != 0) { fprintf(stderr, "curl_formadd error.\n"); return -1; } /* Fill in the submit field too, even if this is rarely needed */ curl_formadd(&post, &last, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "OK", CURLFORM_END); //headerlist = curl_slist_append(headerlist, "Accept-Encoding:UTF-8"); //headerlist = curl_slist_append(headerlist, "Content-type: application/form-data;charset:UTF-8"); headerlist = curl_slist_append(headerlist, buf); //curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if(curl == NULL) { fprintf(stderr, "curl_easy_init() error.\n");curl_formfree(post); return -1; } curl_easy_setopt(curl, CURLOPT_HEADER, 0); curl_easy_setopt(curl, CURLOPT_URL, url); /*Set URL*/ curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); int timeout = 5; curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform[%d] error.\n", res);curl_formfree(post); return -1; } curl_easy_cleanup(curl); return 0;}在实现中,headlist必须有,这个是post的头,没有无法实现上传图片
// TestCurlJsonDlg.h : 头文件//#include "CvvImage.h"#include "opencv/cv.h"#include "opencv/highgui.h"#pragma once// CTestCurlJsonDlg 对话框class CTestCurlJsonDlg : public CDialogEx{// 构造public:CTestCurlJsonDlg(CWnd* pParent = NULL);// 标准构造函数// 对话框数据enum { IDD = IDD_TESTCURLJSON_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV 支持// 实现protected:HICON m_hIcon;// 生成的消息映射函数virtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()public:afx_msg void OnBnClickedButton1();char m_showDate;char m_show2;CString m_show;afx_msg void OnTimer(UINT_PTR nIDEvent);afx_msg void OnBnClickedButton2();afx_msg void OnBnClickedButton3();afx_msg void OnBnClickedButton4();afx_msg void OnBnClickedButton5();};cpp文件
// TestCurlJsonDlg.cpp : 实现文件//#include "stdafx.h"#include "TestCurlJson.h"#include "TestCurlJsonDlg.h"#include "afxdialogex.h"//#include<iostream>//curl添加#include "curl/curl.h"#include <string>#include <sys/stat.h>#include <fcntl.h>#pragma comment(lib, "libcurld_imp.lib") //json#include "json\json.h" #pragma comment(lib,"json_vc71_libmtd.lib")#ifdef _DEBUG#define new DEBUG_NEW#endif//opencv 全局变量CvCapture* capture;CRect rect;CDC *pDC;HDC hDC;CWnd *pwnd;// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialogEx{public:CAboutDlg();// 对话框数据enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持// 实现protected:DECLARE_MESSAGE_MAP()};CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD){}void CAboutDlg::DoDataExchange(CDataExchange* pDX){CDialogEx::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)END_MESSAGE_MAP()// CTestCurlJsonDlg 对话框CTestCurlJsonDlg::CTestCurlJsonDlg(CWnd* pParent /*=NULL*/): CDialogEx(CTestCurlJsonDlg::IDD, pParent), m_show(_T("")){m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);}void CTestCurlJsonDlg::DoDataExchange(CDataExchange* pDX){// 处理MFC默认的数据交换 CDialogEx::DoDataExchange(pDX);DDX_Text(pDX, IDC_EDIT1, m_show);}BEGIN_MESSAGE_MAP(CTestCurlJsonDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_WM_TIMER()ON_BN_CLICKED(IDC_BUTTON1, &CTestCurlJsonDlg::OnBnClickedButton1)ON_BN_CLICKED(IDC_BUTTON2, &CTestCurlJsonDlg::OnBnClickedButton2)ON_BN_CLICKED(IDC_BUTTON3, &CTestCurlJsonDlg::OnBnClickedButton3)ON_BN_CLICKED(IDC_BUTTON4, &CTestCurlJsonDlg::OnBnClickedButton4)ON_BN_CLICKED(IDC_BUTTON5, &CTestCurlJsonDlg::OnBnClickedButton5)END_MESSAGE_MAP()// CTestCurlJsonDlg 消息处理程序BOOL CTestCurlJsonDlg::OnInitDialog(){CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动// 执行此操作SetIcon(m_hIcon, TRUE);// 设置大图标SetIcon(m_hIcon, FALSE);// 设置小图标// TODO: 在此添加额外的初始化代码pwnd = GetDlgItem(IDB_BITMAP1);//pwnd->MoveWindow(35,30,352,288);pDC =pwnd->GetDC();//pDC =GetDC();hDC= pDC->GetSafeHdc();pwnd->GetClientRect(&rect);return TRUE; // 除非将焦点设置到控件,否则返回 TRUE}void CTestCurlJsonDlg::OnSysCommand(UINT nID, LPARAM lParam){if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialogEx::OnSysCommand(nID, lParam);}}// 如果向对话框添加最小化按钮,则需要下面的代码// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,// 这将由框架自动完成。void CTestCurlJsonDlg::OnPaint(){if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialogEx::OnPaint();}}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CTestCurlJsonDlg::OnQueryDragIcon(){return static_cast<HCURSOR>(m_hIcon);}void CTestCurlJsonDlg::OnTimer(UINT_PTR nIDEvent){// TODO: Add your message handler code here and/or call default/************************************************************************//* 显示摄像头 *//************************************************************************/IplImage* m_Frame;m_Frame=cvQueryFrame(capture);CvvImage m_CvvImage;m_CvvImage.CopyOf(m_Frame,1);if (true){m_CvvImage.DrawToHDC(hDC, &rect);//cvWaitKey(10);}CDialog::OnTimer(nIDEvent);}//curl回调方法size_t http_data_writer(void* data, size_t size, size_t nmemb, void* content) { long totalSize = size*nmemb; std::string* symbolBuffer = (std::string*)content; if(symbolBuffer) { symbolBuffer->append((char *)data, ((char*)data)+totalSize); } return totalSize; }//转换格式wchar_t* ConvertUtf8ToUnicode(const char* utf8){if(!utf8){wchar_t* buf = (wchar_t*)malloc(2);memset(buf,0,2);return buf;}int nLen = ::MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,(LPCSTR)utf8,-1,NULL,0);//返回需要的unicode长度 WCHAR * wszUNICODE = new WCHAR[nLen+1]; memset(wszUNICODE, 0, nLen * 2 + 2); nLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8, -1, wszUNICODE, nLen); //把utf8转成unicodereturn wszUNICODE;}std::string wstring2string(const std::wstring & wstr){ std::string str(""); int nLen = WideCharToMultiByte(CP_ACP,0,(LPCWSTR)wstr.c_str(),(int)wstr.length(),NULL,0,NULL,NULL); if(nLen <= 0) {return str;} str.resize(nLen,'\0'); WideCharToMultiByte(CP_ACP,0,(LPCWSTR)wstr.c_str(),(int)wstr.length(),(LPSTR)str.c_str(),nLen,NULL,NULL); return str ;}std::wstring string2wstring(const std::string & str){ std::wstring wstr(L""); int nLen = MultiByteToWideChar(CP_ACP,0,(LPCSTR)str.c_str(),(int)str.length(),0,0); if(nLen <= 0){return wstr;} wstr.resize(nLen,L'\0'); MultiByteToWideChar(CP_ACP,0,(LPCSTR)str.c_str(),(int)str.length(),(LPWSTR)wstr.c_str(),nLen); return wstr;}std::string U2Utf(const std::wstring& wstrUnicode)//Unicode转utf8 { std::string strRet; if( wstrUnicode.empty() ) return strRet; int nLen = WideCharToMultiByte(CP_UTF8, 0, wstrUnicode.c_str(), -1, NULL, 0, NULL, NULL); char* pBuffer=new char[nLen+1]; pBuffer[nLen] = '\0'; nLen = WideCharToMultiByte(CP_UTF8, 0, wstrUnicode.c_str(), -1, pBuffer, nLen, NULL, NULL); strRet.append(pBuffer); delete[] pBuffer; return strRet; } void CTestCurlJsonDlg::OnBnClickedButton1(){//已实现传递和调用参数 CURL *curl; CURLcode code; curl = curl_easy_init(); if (curl) {curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.116:8080/TianMen/PushExitMessageAction!test.action"); // 指定urlstd::string licenstr = "licensePlate=鄂A123456&driverName=张三"; //const char* licenChar = licenstr.c_str();std::wstring licenwstr = string2wstring(licenstr);licenstr = U2Utf(licenwstr);//std::string canshu = licenstr;curl_easy_setopt(curl, CURLOPT_POSTFIELDS, licenstr.c_str()); //传递参数 参数必须是const char*//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "licensePlate=abcd123"); //传递参数curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_data_writer); //回调函数//设置写数据 回调函数必须有 std::string strData; curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&strData); // 执行请求 code = curl_easy_perform(curl); if(code == CURLcode::CURLE_OK) { UpdateData(TRUE); std::string result; long responseCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode); if (responseCode < 200 || responseCode >= 300 || strData.empty()) { curl_easy_cleanup(curl);return ; } const char *p=strData.data();WCHAR *p_new = ConvertUtf8ToUnicode(p);std::string p_str = wstring2string(p_new);Json::Reader reader;//json解析 Json::Value value;//表示一个json格式的对象if(reader.parse(p_str,value))//解析出json放到json中区 { std::string total=value["total"].asString(); std::string out;result.append(value["licensePlate"].asString()+"\n");result.append(value["driverName"].asString()+"\n");//std::cout<<total<<std::endl; const Json::Value arrayObj=value["rows"];//迭代器 for (int i=0; i < arrayObj.size();i++) { out=arrayObj[i]["shiftNumber"].asString(); //m_show = out; //m_show = out.c_str();result.append(out);} } m_show = result.c_str(); UpdateData(FALSE); getchar(); } } curl_easy_cleanup(curl);}int http_post_file(const char *url, const char *filename){ CURL *curl = NULL; CURLcode res; struct curl_httppost *post=NULL; struct curl_httppost *last=NULL; struct curl_slist *headerlist=NULL; static const char buf[] = "Expect:"; if(filename == NULL || url == NULL) return -1; printf("URL: %s\n", url); printf("filename: %s\n", filename); /* Add simple file section */ if( curl_formadd(&post, &last, CURLFORM_COPYNAME, "file", CURLFORM_FILE, filename, CURLFORM_END) != 0) { fprintf(stderr, "curl_formadd error.\n"); return -1; } /* Fill in the submit field too, even if this is rarely needed */ curl_formadd(&post, &last, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "OK", CURLFORM_END); //headerlist = curl_slist_append(headerlist, "Accept-Encoding:UTF-8"); //headerlist = curl_slist_append(headerlist, "Content-type: application/form-data;charset:UTF-8"); headerlist = curl_slist_append(headerlist, buf); //curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if(curl == NULL) { fprintf(stderr, "curl_easy_init() error.\n");curl_formfree(post); return -1; } curl_easy_setopt(curl, CURLOPT_HEADER, 0); curl_easy_setopt(curl, CURLOPT_URL, url); /*Set URL*/ curl_easy_setopt(curl, CURLOPT_HTTPPOST, post); int timeout = 5; curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1); res = curl_easy_perform(curl); if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform[%d] error.\n", res);curl_formfree(post); return -1; } curl_easy_cleanup(curl); return 0;}void CTestCurlJsonDlg::OnBnClickedButton2(){// TODO: 在此添加控件通知处理程序代码//char sFilePath[128]="d:\\abc\1.bmp";//const char * localfile = "F:\\abc\\123456ab.bmp";const char * localfile = "C:/Users/admin/Documents/Visual Studio 2010/Projects/TestCurlJson/TestCurlJson/1123.bmp"; //POST File http_post_file("http://192.168.0.116:8080/TianMen/UploadFile.servlet", localfile);getchar();}void CTestCurlJsonDlg::OnBnClickedButton3(){// TODO: 在此添加控件通知处理程序代码if(!capture){capture = cvCaptureFromCAM(0);//AfxMessageBox("OK");}if (!capture){//AfxMessageBox("无法打开摄像头");return;}// 测试IplImage* m_Frame;m_Frame=cvQueryFrame(capture);CvvImage m_CvvImage;m_CvvImage.CopyOf(m_Frame,1);if (true){m_CvvImage.DrawToHDC(hDC, &rect);//cvWaitKey(10);}// 设置计时器,每10ms触发一次事件SetTimer(1,10,NULL);}void CTestCurlJsonDlg::OnBnClickedButton4(){// TODO: 在此添加控件通知处理程序代码cvReleaseCapture(&capture);CDC MemDC; CBitmap m_Bitmap1;m_Bitmap1.LoadBitmap(IDB_BITMAP1); MemDC.CreateCompatibleDC(NULL);MemDC.SelectObject(&m_Bitmap1);pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&MemDC,0,0,48,48,SRCCOPY); }void CTestCurlJsonDlg::OnBnClickedButton5(){// TODO: 在此添加控件通知处理程序代码 if (!capture)return;IplImage * m_GrabFrame=cvQueryFrame(capture);if (!m_GrabFrame)return;/*staticchar countsnap='1';CString m_name="";m_name=+countsnap;m_name+=".bmp"; */IplImage * m_snap=cvCreateImage(cvGetSize(m_GrabFrame),m_GrabFrame->depth,m_GrabFrame->nChannels);cvCopy(m_GrabFrame,m_snap,NULL);const char* pFileName = "1123.bmp";cvSaveImage(pFileName,m_snap);//把图像写入文件 //CString BmpName = dlg.GetPathName(); //获取文件路径名 如 D:\pic\abc.bmp 路径std::string fileName(pFileName);std::string fileRoad = "C:/Users/admin/Documents/Visual Studio 2010/Projects/TestCurlJson/TestCurlJson/"+fileName;CString BmpName = string2wstring(fileRoad).c_str(); //CString EntName = dlg.GetFileExt(); //获取文件扩展名 bmp //定义变量存储图片信息 BITMAPINFO *pBmpInfo; //记录图像细节 BYTE *pBmpData; //图像数据 BITMAPFILEHEADER bmpHeader; //文件头 BITMAPINFOHEADER bmpInfo; //信息头 CFile bmpFile; //记录打开文件 //以只读的方式打开文件 读取bmp图片各部分 bmp文件头 信息 数据 if(!bmpFile.Open(BmpName, CFile::modeRead|CFile::typeBinary)) return; if (bmpFile.Read(&bmpHeader,sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER)) return; if (bmpFile.Read(&bmpInfo,sizeof(BITMAPINFOHEADER)) != sizeof(BITMAPINFOHEADER)) return; pBmpInfo = (BITMAPINFO *)new char[sizeof(BITMAPINFOHEADER)]; //为图像数据申请空间 memcpy(pBmpInfo,&bmpInfo,sizeof(BITMAPINFOHEADER)); DWORD dataBytes = bmpHeader.bfSize - bmpHeader.bfOffBits; pBmpData = (BYTE*)new char[dataBytes]; bmpFile.Read(pBmpData,dataBytes); bmpFile.Close(); //显示图像 CWnd *pWnd=GetDlgItem(IDC_SHOW); //获得pictrue控件窗口的句柄 CRect rect; pWnd->GetClientRect(&rect); //获得pictrue控件所在的矩形区域 CDC *pDC=pWnd->GetDC(); //获得pictrue控件的DC pDC->SetStretchBltMode(COLORONCOLOR); StretchDIBits(pDC->GetSafeHdc(),0,0,rect.Width(),rect.Height(),0,0, bmpInfo.biWidth,bmpInfo.biHeight,pBmpData,pBmpInfo,DIB_RGB_COLORS,SRCCOPY);}最后,展示一下效果
- MFC调用摄像头拍照,通过curl把图片传给java后台
- 通过调用系统摄像头拍照,拍视频
- ios 通过调用系统摄像头拍照,…
- 调用摄像头拍照以及上传图片
- 使用Java调用摄像头进行拍照源码
- MFC 通过opencv打开摄像头 拍照后显示保存
- thread线程,UI线程与后台线程,后台线程把message通过handler传给UI线程
- 在MFC图片控件中打开摄像头实时拍照
- 通过调用系统摄像头拍照,拍视频,然后写入文件
- iOS_调用摄像头拍照
- android 调用摄像头拍照
- IOS 调用摄像头拍照
- Android 调用摄像头拍照
- 调用摄像头拍照
- 调用摄像头拍照
- 调用摄像头拍照 camera
- unity调用摄像头拍照
- 调用摄像头拍照
- 《PCL点云库学习&VS2010(X64)》Part 18 PCL1.72(VTK6.2.0)编译CloudCompare注意点
- JAVA MD5 加密与解密
- 从sql server 到Oracle使用openquery带参数查询
- c++模板函数声明定义分离编译错误详解
- Xcode常用快捷键
- MFC调用摄像头拍照,通过curl把图片传给java后台
- tcp通讯的方式并使用socket建立客户端与服务器的通信的过程
- 设计模式六大原则
- Leetcode: 4Sum
- 基于html中canvas标签的验证码图片生成方法
- webuploader踩坑
- 机器学习算法疗程(logistic 回归)
- Linux动态库,静态库
- Yii2 认识(1)