cv.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. // cv.cpp : 定义 DLL 的导出函数。
  2. //
  3. #include "stdafx.h"
  4. #include "framework.h"
  5. #include "cv.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #endif
  9. #ifdef _DEBUG
  10. extern void test();
  11. extern void test2();
  12. #endif
  13. // 唯一的应用程序对象
  14. CWinApp theApp;
  15. using namespace std;
  16. int main()
  17. {
  18. int nRetCode = 0;
  19. HMODULE hModule = ::GetModuleHandle(nullptr);
  20. if (hModule != nullptr)
  21. {
  22. // 初始化 MFC 并在失败时显示错误
  23. if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
  24. {
  25. // TODO: 在此处为应用程序的行为编写代码。
  26. _tprintf(_T("错误: MFC 初始化失败\n"));
  27. nRetCode = 1;
  28. }
  29. else
  30. {
  31. // TODO: 在此处为应用程序的行为编写代码。
  32. #ifdef _DEBUG
  33. test2();
  34. #endif
  35. }
  36. }
  37. else
  38. {
  39. // TODO: 更改错误代码以符合需要
  40. _tprintf(_T("错误: GetModuleHandle 失败\n"));
  41. nRetCode = 1;
  42. }
  43. return nRetCode;
  44. }
  45. // gdiplus token;
  46. ULONG_PTR g_gdiplusToken;
  47. // 初始化gid+环境;
  48. void InitGdiplus() {
  49. Gdiplus::GdiplusStartupInput gdiplusStartupInput;
  50. Gdiplus::GdiplusStartup(&g_gdiplusToken, &gdiplusStartupInput, NULL);
  51. }
  52. void ShutGdiplus() {
  53. Gdiplus::GdiplusShutdown(g_gdiplusToken);
  54. }
  55. CV_API bool GdiplusReadImage(std::string strImgPath, Gdiplus::Bitmap** bitmap)
  56. {
  57. // 参数有效性判断;
  58. if (!PathFileExists(strImgPath.c_str())) {
  59. #ifdef _DEBUG
  60. OutputDebugString("参数无效!");
  61. #endif
  62. return false;
  63. }
  64. #ifdef UNICODE
  65. *bitmap = Image::FromFile(strImgPath.c_str());
  66. #else
  67. // #include <comutil.h>
  68. BSTR strtmp = _bstr_t(strImgPath.c_str());
  69. *bitmap = Gdiplus::Bitmap::FromFile(strtmp, TRUE);
  70. SysFreeString(strtmp);
  71. if (*bitmap == NULL)
  72. return false;
  73. #endif
  74. return true;
  75. }
  76. CV_API bool GdiReadImage(std::string strImgPath, CBitmap& bitmap)
  77. {
  78. // 参数有效性判断;
  79. if (!PathFileExists(strImgPath.c_str())) {
  80. #ifdef _DEBUG
  81. OutputDebugString("参数无效!");
  82. #endif
  83. return false;
  84. }
  85. // 注意:CBitmap是无法直接加载文件;
  86. HBITMAP hBitmap;
  87. //从文件中加载,使用HBITMAP;
  88. hBitmap = (HBITMAP)::LoadImage(
  89. //::AfxGetInstanceHandle(),
  90. NULL, // oem image
  91. strImgPath.c_str(),
  92. IMAGE_BITMAP,
  93. 0, // cx
  94. 0, // cy
  95. // 如果是兼容位图,去掉LR_CREATEDIBSECTION
  96. LR_LOADFROMFILE|LR_CREATEDIBSECTION
  97. );
  98. // 附加资源;
  99. bitmap.Attach(hBitmap);
  100. if ( bitmap.m_hObject == NULL ) {
  101. return false;
  102. }
  103. /*
  104. hBmp=(HBITMAP)bmp.GetSafeHandle();
  105. */
  106. return true;
  107. }
  108. CV_API bool ReadImage(std::string strImgPath, cv::Mat& img)
  109. {
  110. // 参数有效性判断;
  111. if (!PathFileExists(strImgPath.c_str())) {
  112. #ifdef _DEBUG
  113. OutputDebugString("参数无效!");
  114. #endif
  115. return false;
  116. }
  117. // 以BGR三通道方式读取图片;
  118. img = cv::imread(strImgPath.c_str(), cv::IMREAD_COLOR);
  119. // 判断图片是否为空;
  120. if (img.empty()) {
  121. #ifdef _DEBUG
  122. OutputDebugString("读取图片失败!");
  123. #endif
  124. return false;
  125. }
  126. return true;
  127. }
  128. CV_API bool GetBinaryImage(std::string strImgPath, long nThresholdVal, long nMaxThresholdVal, cv::Mat& thresholdImg)
  129. {
  130. cv::Mat img;
  131. // 读取图片;
  132. if (!ReadImage(strImgPath, img))
  133. return false;
  134. cv::Mat grayImg;
  135. // 转成灰阶图;
  136. cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
  137. // 释放对象;
  138. img.release();
  139. cv::Mat gaussImg;
  140. // 再高斯模糊处理(滤波);
  141. cv::GaussianBlur(grayImg, gaussImg, cv::Size(5, 5), 0, 0);
  142. // 释放对象;
  143. grayImg.release();
  144. // 全局化指定的阀值与返回值相等;
  145. cv::threshold(gaussImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY);
  146. // 释放对象;
  147. gaussImg.release();
  148. // 判断图片是否空;
  149. if (thresholdImg.empty())
  150. return false;
  151. return true;
  152. }
  153. CV_API bool GetOTSUBinaryImage(std::string strImgPath, long nThresholdVal, long nMaxThresholdVal, cv::Mat& thresholdImg)
  154. {
  155. cv::Mat img;
  156. // 读取图片;
  157. if (!ReadImage(strImgPath, img))
  158. return false;
  159. cv::Mat grayImg;
  160. // 转成灰阶图;
  161. cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
  162. // 释放对象;
  163. img.release();
  164. cv::Mat gaussImg;
  165. // 再高斯模糊处理(滤波);
  166. cv::GaussianBlur(grayImg, gaussImg, cv::Size(5, 5), 0, 0);
  167. // 释放对象;
  168. grayImg.release();
  169. // OTSU,此时参数3可随意设置;
  170. cv::threshold(gaussImg, thresholdImg, nThresholdVal, nMaxThresholdVal, cv::THRESH_BINARY | cv::THRESH_OTSU);
  171. // 释放对象;
  172. gaussImg.release();
  173. // 判断图片是否空;
  174. if (thresholdImg.empty())
  175. return false;
  176. return true;
  177. }
  178. CV_API bool GetAdaptiveBinaryImage(std::string strImgPath, long nMaxThresholdVal, cv::Mat& thresholdImg)
  179. {
  180. cv::Mat img;
  181. // 读取图片;
  182. if (!ReadImage(strImgPath, img))
  183. return false;
  184. cv::Mat grayImg;
  185. // 转成灰阶图;
  186. cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
  187. // 释放对象;
  188. img.release();
  189. cv::Mat gaussImg;
  190. // 再高斯模糊处理(滤波);
  191. cv::GaussianBlur(grayImg, gaussImg, cv::Size(5, 5), 0, 0);
  192. // 释放对象;
  193. grayImg.release();
  194. cv::Mat blurImg;
  195. // 自适应阀值;
  196. cv::medianBlur(gaussImg, blurImg, 3);
  197. // 释放对象;
  198. gaussImg.release();
  199. // 局部二值化;//blocksize一般取3、5、7
  200. cv::adaptiveThreshold(blurImg, thresholdImg, nMaxThresholdVal, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 3, 4.5);
  201. // 释放对象;
  202. blurImg.release();
  203. // 判断图片是否空;
  204. if (thresholdImg.empty())
  205. return false;
  206. return true;
  207. }
  208. CV_API bool GaussianBlur(cv::Mat& img, cv::Size cvSize, cv::Mat& gaussImg)
  209. {
  210. if (img.empty())
  211. return false;
  212. // 再高斯模糊处理(滤波);
  213. cv::GaussianBlur(img, gaussImg, cvSize, 0, 0);
  214. // 判断图片是否空;
  215. if (gaussImg.empty())
  216. return false;
  217. return true;
  218. }
  219. CV_API bool GaussianBlur(std::string strImgPath, cv::Size cvSize, cv::Mat& gaussImg)
  220. {
  221. cv::Mat img;
  222. // 读取图片;
  223. if (!ReadImage(strImgPath, img))
  224. return false;
  225. // 再高斯模糊处理(滤波);
  226. cv::GaussianBlur(img, gaussImg, cvSize, 0, 0);
  227. // 判断图片是否空;
  228. if (gaussImg.empty())
  229. return false;
  230. return true;
  231. }
  232. CV_API bool Color2Gray(cv::Mat& img, cv::Mat& grayImg)
  233. {
  234. if (img.empty())
  235. return false;
  236. // 再高斯模糊处理(滤波);
  237. cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
  238. // 判断图片是否空;
  239. if (grayImg.empty())
  240. return false;
  241. return true;
  242. }
  243. CV_API bool Color2Gray(std::string strImgPath, cv::Mat& grayImg)
  244. {
  245. cv::Mat img;
  246. // 读取图片;
  247. if (!ReadImage(strImgPath, img))
  248. return false;
  249. // 再高斯模糊处理(滤波);
  250. cv::cvtColor(img, grayImg, cv::COLOR_BGR2GRAY);
  251. // 判断图片是否空;
  252. if (grayImg.empty())
  253. return false;
  254. return true;
  255. }
  256. CV_API bool Gray2Color(cv::Mat& img, cv::Mat& colorImg)
  257. {
  258. if (img.empty())
  259. return false;
  260. // 再高斯模糊处理(滤波);
  261. cv::cvtColor(img, colorImg, cv::COLOR_GRAY2BGR);
  262. // 判断图片是否空;
  263. if (colorImg.empty())
  264. return false;
  265. return true;
  266. }
  267. CV_API bool ErodeImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelSize, cv::Mat& erodeImg)
  268. {
  269. if (img.empty())
  270. return false;
  271. // 获取自定义核(核形状:矩形MORPH_RECT、十字架CROSS、椭圆ELLIPSE )
  272. cv::Mat element = cv::getStructuringElement(kernelShape, kernelSize);
  273. // 再高斯模糊处理(滤波);
  274. cv::erode(img, erodeImg, element);
  275. // 判断图片是否空;
  276. if (erodeImg.empty())
  277. return false;
  278. return true;
  279. }
  280. CV_API bool DilateImg(cv::Mat& img, cv::MorphShapes kernelShape, cv::Size kernelSize, cv::Mat& dilateImg)
  281. {
  282. if (img.empty())
  283. return false;
  284. // 获取自定义核(核形状:矩形MORPH_RECT、十字架CROSS、椭圆ELLIPSE )
  285. cv::Mat element = cv::getStructuringElement(kernelShape, kernelSize);
  286. // 再高斯模糊处理(滤波);
  287. cv::dilate(img, dilateImg, element);
  288. // 判断图片是否空;
  289. if (dilateImg.empty())
  290. return false;
  291. return true;
  292. }
  293. CV_API bool CutPictures(cv::Mat& img, cv::Rect cvRect, cv::Mat& roiImg)
  294. {
  295. if (img.empty())
  296. return false;
  297. if (cvRect.empty())
  298. return false;
  299. // 裁剪ROI区域;
  300. roiImg = img(cvRect);
  301. // 判断图片是否空;
  302. if (roiImg.empty())
  303. return false;
  304. return true;
  305. }
  306. CV_API bool CutPictures(std::string strImgPath, cv::Rect cvRect, cv::Mat& roiImg)
  307. {
  308. cv::Mat img;
  309. // 读取图片;
  310. if (!ReadImage(strImgPath, img))
  311. return false;
  312. if (cvRect.empty())
  313. return false;
  314. // 裁剪ROI区域;
  315. roiImg = img(cvRect);
  316. // 释放原图;
  317. img.release();
  318. // 判断图片是否空;
  319. if (roiImg.empty())
  320. return false;
  321. return true;
  322. }
  323. CV_API bool CutPictures(std::string strImgPath, cv::Rect cvRect, std::string strRoiImgPath)
  324. {
  325. cv::Mat img;
  326. // 读取图片;
  327. if (!ReadImage(strImgPath, img))
  328. return false;
  329. if (cvRect.empty())
  330. return false;
  331. cv::Mat roiImg;
  332. // 裁剪ROI区域;
  333. roiImg = img(cvRect);
  334. // 释放原图;
  335. img.release();
  336. // 判断图片是否空;
  337. if (roiImg.empty())
  338. return false;
  339. cv::imwrite(strRoiImgPath.c_str(), roiImg);
  340. roiImg.release();
  341. return true;
  342. }
  343. CV_API bool DrawContours(cv::Mat& binImg, cv::Mat& drawImg, bool InternalContour, bool bPerimeter, long nMinPerimeter, long nMaxPerimeter, bool bArea, long nMinArea, long nMaxArea)
  344. {
  345. // 图片空或都不是单通道;
  346. if (binImg.empty() || binImg.channels() > 1)
  347. return false;
  348. if (drawImg.empty()) {
  349. // 复制到目标中;
  350. binImg.copyTo(drawImg);
  351. // 再转为BGR;
  352. cv::cvtColor(drawImg, drawImg, cv::COLOR_GRAY2BGR);
  353. }
  354. // 轮廓;
  355. vector<vector<cv::Point>> contours;
  356. // 轮廓关系;
  357. vector<cv::Vec4i> hierarchy;
  358. // 获取轮廓区域;
  359. if (InternalContour)
  360. {
  361. // 所有轮廓,内外轮廓分等级;
  362. findContours(binImg, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
  363. // 所有轮廓,内外轮廓不分等级,独立;
  364. //findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
  365. }
  366. else
  367. {
  368. // RETR_EXTERNAL=只检索最外面的轮廓;
  369. findContours(binImg, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
  370. }
  371. vector<vector<cv::Point>>::iterator it = contours.begin();
  372. for (int i = 0; it != contours.end(); it++, i++)
  373. {
  374. if (bPerimeter && !bArea)
  375. {
  376. if (arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter)
  377. continue;
  378. }
  379. else if (!bPerimeter && bArea)
  380. {
  381. if (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea)
  382. continue;
  383. }
  384. else if (bArea && bPerimeter)
  385. {
  386. if ((arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter) || (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea))
  387. continue;
  388. }
  389. // 随机色填充轮廓;
  390. cv::Scalar color = cv::Scalar(rand() % 255, rand() % 255, rand() % 255);
  391. // 输出轮廓图;
  392. cv::drawContours(drawImg, contours, i, color, cv::FILLED, 8, hierarchy);
  393. }
  394. if (drawImg.empty())
  395. return false;
  396. return true;
  397. }
  398. CV_API bool MatchSingleImage(cv::Mat& img, cv::Mat templImg, double& matchVal, cv::Rect& matchRect)
  399. {
  400. if (img.empty() || templImg.empty())
  401. return false;
  402. /*
  403. 模板匹配的匹配方式:
  404. 0:CV_TM_SQDIFF 平方差匹配法:最好匹配为0。 匹配越差,匹配值越大。
  405. 这类方法利用图像与模板各个像素差值的平方和来进行匹配,最好匹配为 0。 匹配越差,匹配值越大。
  406. 1:CV_TM_SQDIFF_NORMED 归一化平方差匹配法:最好匹配为0。 匹配越差,匹配值越大。
  407. 这个方法其实和差值平方和算法是类似的。只不过对图像和模板进行了标准化操作
  408. 2:CV_TM_CCORR 相关匹配法:0最差匹配,越接近1越完美;
  409. 这类方法采用模板和图像的互相关计算作为相似度的度量方法,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。
  410. 3:CV_TM_CCORR_NORMED 归一化相关匹配法:0最差匹配,越接近1越完美;
  411. 这个方法和 标准化差值平方和匹配 类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。
  412. 4:CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
  413. 这种方法也叫做相关匹配,但是和上面的 CV_TM_CCORR 匹配方法还是有不通过的。简单的说,这里是把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量
  414. 5:CV_TM_CCOEFF_NORMED 归一化相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
  415. 这是 OpenCV 支持的最复杂的一种相似度算法。
  416. 这里的相关运算就是数理统计学科的相关系数计算方法。
  417. 具体的说,就是在减去了各自的平均值之外,还要各自除以各自的方差。
  418. 经过减去平均值和除以方差这么两步操作之后,无论是我们的待检图像还是模板都被标准化了,
  419. 这样可以保证图像和模板分别改变光照亮不影响计算结果。计算出的相关系数被限制在了 -1 到 1 之间,
  420. 1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示两幅图像之间没有线性关系。
  421. */
  422. cv::Mat resultImg;
  423. cv::matchTemplate(img, templImg, resultImg, cv::TM_CCOEFF_NORMED);
  424. if (resultImg.empty())
  425. return false;
  426. // 最小和最大匹配值;
  427. double lv_nMinVal = 0.0;
  428. double lv_nMaxVal = 0.0;
  429. // 匹配的坐标点;
  430. cv::Point lv_nMinLoc = cv::Point(0, 0);
  431. cv::Point lv_nMaxLoc = cv::Point(0, 0);
  432. cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  433. // TM_CCOEFF_NORMED匹配是取最大值为匹配值;
  434. matchVal = lv_nMaxVal;
  435. // 匹配区域,使用最大区域;
  436. matchRect.x = lv_nMaxLoc.x;
  437. matchRect.y = lv_nMaxLoc.y;
  438. matchRect.width = templImg.cols;
  439. matchRect.height = templImg.rows;
  440. #ifdef _DEBUG
  441. // 在原图上框出模板位置;
  442. cv::Mat showImg;
  443. img.copyTo(showImg);
  444. cv::rectangle(showImg,
  445. cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
  446. cv::Point(lv_nMaxLoc.x + templImg.cols, lv_nMaxLoc.y + templImg.rows),
  447. cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
  448. 2,
  449. cv::LINE_AA,
  450. 0);
  451. // 输出到文件中;
  452. imwrite("showImg.png", showImg);
  453. // 释放对象;
  454. showImg.release();
  455. #endif
  456. // 释放对象;
  457. resultImg.release();
  458. return true;
  459. }
  460. CV_API bool MatchSingleImage(cv::Mat& img, std::string strTmpImg, double& matchVal, cv::Rect& matchRect)
  461. {
  462. if (img.empty())
  463. return false;
  464. // 读取模板图片;
  465. cv::Mat templImg = imread(strTmpImg.c_str(), cv::IMREAD_COLOR);
  466. if (templImg.empty()) {
  467. return false;
  468. }
  469. cv::Mat resultImg;
  470. cv::matchTemplate(img, templImg, resultImg, cv::TM_CCOEFF_NORMED);
  471. if (resultImg.empty()) {
  472. templImg.release();
  473. return false;
  474. }
  475. // 最小和最大匹配值;
  476. double lv_nMinVal = 0.0;
  477. double lv_nMaxVal = 0.0;
  478. // 匹配的坐标点;
  479. cv::Point lv_nMinLoc = cv::Point(0, 0);
  480. cv::Point lv_nMaxLoc = cv::Point(0, 0);
  481. cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  482. // TM_CCOEFF_NORMED匹配是取最大值为匹配值;
  483. matchVal = lv_nMaxVal;
  484. // 匹配区域,使用最大区域;
  485. matchRect.x = lv_nMaxLoc.x;
  486. matchRect.y = lv_nMaxLoc.y;
  487. matchRect.width = templImg.cols;
  488. matchRect.height = templImg.rows;
  489. #ifdef _DEBUG
  490. // 在原图上框出模板位置;
  491. cv::Mat showImg;
  492. img.copyTo(showImg);
  493. cv::rectangle(showImg,
  494. cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
  495. cv::Point(lv_nMaxLoc.x + templImg.cols, lv_nMaxLoc.y + templImg.rows),
  496. cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
  497. 2,
  498. cv::LINE_AA,
  499. 0);
  500. // 输出到文件中;
  501. imwrite("showImg.png", showImg);
  502. // 释放对象;
  503. showImg.release();
  504. #endif
  505. // 释放对象;
  506. templImg.release();
  507. resultImg.release();
  508. return true;
  509. }
  510. CV_API bool MatchSingleImage(std::string strImg, std::string strTmpImg, double& matchVal, cv::Rect& matchRect)
  511. {
  512. cv::Mat img;
  513. cv::Mat templImg;
  514. if (!ReadImage(strImg.c_str(), img) )
  515. return false;
  516. if (!ReadImage(strTmpImg.c_str(), templImg)) {
  517. img.release();
  518. return false;
  519. }
  520. cv::Mat resultImg;
  521. cv::matchTemplate(img, templImg, resultImg, cv::TM_CCOEFF_NORMED);
  522. if (resultImg.empty()) {
  523. img.release();
  524. templImg.release();
  525. return false;
  526. }
  527. // 最小和最大匹配值;
  528. double lv_nMinVal = 0.0;
  529. double lv_nMaxVal = 0.0;
  530. // 匹配的坐标点;
  531. cv::Point lv_nMinLoc = cv::Point(0, 0);
  532. cv::Point lv_nMaxLoc = cv::Point(0, 0);
  533. cv::minMaxLoc(resultImg, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  534. // TM_CCOEFF_NORMED匹配是取最大值为匹配值;
  535. matchVal = lv_nMaxVal;
  536. // 匹配区域,使用最大区域;
  537. matchRect.x = lv_nMaxLoc.x;
  538. matchRect.y = lv_nMaxLoc.y;
  539. matchRect.width = templImg.cols;
  540. matchRect.height = templImg.rows;
  541. #ifdef _DEBUG
  542. // 在原图上框出模板位置;
  543. cv::Mat showImg;
  544. img.copyTo(showImg);
  545. cv::rectangle(showImg,
  546. cv::Point(lv_nMaxLoc.x, lv_nMaxLoc.y),
  547. cv::Point(lv_nMaxLoc.x + templImg.cols, lv_nMaxLoc.y + templImg.rows),
  548. cv::Scalar(rand() % 255, rand() % 255, rand() % 255),
  549. 2,
  550. cv::LINE_AA,
  551. 0);
  552. // 输出到文件中;
  553. imwrite("showImg.png", showImg);
  554. // 释放对象;
  555. showImg.release();
  556. #endif
  557. // 释放对象;
  558. img.release();
  559. templImg.release();
  560. resultImg.release();
  561. return true;
  562. }
  563. CV_API bool Mat2Bitmap(cv::Mat& img, CBitmap& bitmap)
  564. {
  565. return CV_API bool();
  566. }
  567. CV_API bool Mat2HBitmap(cv::Mat& img, HBITMAP& bitmap)
  568. {
  569. //MAT类的TYPE=(nChannels-1+ CV_8U)<<3
  570. int nChannels = (img.type() >> 3) - CV_8U + 1;
  571. int iSize = img.cols * img.rows * nChannels;
  572. bitmap = CreateBitmap(img.cols, img.rows, 1, nChannels * 8, img.data);
  573. return true;
  574. }
  575. CV_API bool Mat2GdiplusBitmap(cv::Mat& img, Gdiplus::Bitmap& bitmap)
  576. {
  577. cv::Mat temp = img.clone();
  578. if (temp.channels() == 1 ) {
  579. cv::cvtColor(img, temp, cv::COLOR_GRAY2BGR);
  580. }
  581. Gdiplus::Bitmap bitmap2(temp.cols, temp.rows, temp.step1(), PixelFormat24bppRGB, temp.data);
  582. //bitmap = bitmap2;
  583. //bitmap2.
  584. Gdiplus::Rect rect(0,0, temp.cols, temp.rows);
  585. return CV_API bool();
  586. }
  587. CV_API bool Bitmap2Mat(CBitmap& bitmap, cv::Mat& img)
  588. {
  589. return CV_API bool();
  590. }
  591. CV_API bool HBitmap2Mat(HBITMAP& bitmap, cv::Mat& img)
  592. {
  593. return CV_API bool();
  594. }
  595. // 能转,但转出来的gdiplus的图片与opencv的大小存在差异;
  596. CV_API bool GdiplusBitmap2Mat(Gdiplus::Bitmap* bitmap, cv::Mat& img)
  597. {
  598. Gdiplus::PixelFormat format = bitmap->GetPixelFormat();
  599. if (format != PixelFormat24bppRGB)
  600. return false;
  601. int width = bitmap->GetWidth();
  602. int height = bitmap->GetHeight();
  603. Gdiplus::Rect rcLock(0,0,width,height);
  604. Gdiplus::BitmapData bmpData;
  605. if ( !bitmap->LockBits(&rcLock, Gdiplus::ImageLockModeRead, format, &bmpData) == Gdiplus::Ok )
  606. {
  607. return false;
  608. }
  609. img = cv::Mat(height, width, CV_8UC3, static_cast<unsigned char*>(bmpData.Scan0), bmpData.Stride).clone();
  610. bitmap->UnlockBits(&bmpData);
  611. if (img.empty())
  612. return false;
  613. return true;
  614. }