ThresholdToolsDlg.cpp 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  1. 
  2. // ThresholdToolsDlg.cpp: 实现文件
  3. //
  4. #include "stdafx.h"
  5. #include "ThresholdTools.h"
  6. #include "ThresholdToolsDlg.h"
  7. #include "afxdialogex.h"
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #endif
  11. // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
  12. class CAboutDlg : public CDialogEx
  13. {
  14. public:
  15. CAboutDlg();
  16. // 对话框数据
  17. #ifdef AFX_DESIGN_TIME
  18. enum { IDD = IDD_ABOUTBOX };
  19. #endif
  20. protected:
  21. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
  22. // 实现
  23. protected:
  24. DECLARE_MESSAGE_MAP()
  25. };
  26. CAboutDlg::CAboutDlg() : CDialogEx(IDD_ABOUTBOX)
  27. {
  28. }
  29. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  30. {
  31. CDialogEx::DoDataExchange(pDX);
  32. }
  33. BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
  34. END_MESSAGE_MAP()
  35. // CThresholdToolsDlg 对话框
  36. CThresholdToolsDlg::CThresholdToolsDlg(CWnd* pParent /*=nullptr*/)
  37. : CDialogEx(IDD_THRESHOLDTOOLS_DIALOG, pParent)
  38. , m_strMaxVal(_T(""))
  39. , m_strLeft(_T(""))
  40. , m_strTop(_T(""))
  41. , m_strRight(_T(""))
  42. , m_strBottom(_T(""))
  43. , m_bThreshold(FALSE)
  44. {
  45. m_strMaxVal = _T("255");
  46. m_nRadio = 0;
  47. m_bPress = FALSE;
  48. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  49. }
  50. void CThresholdToolsDlg::DoDataExchange(CDataExchange* pDX)
  51. {
  52. CDialogEx::DoDataExchange(pDX);
  53. DDX_Control(pDX, IDC_SLIDER1, m_slider);
  54. DDX_Text(pDX, IDC_EDIT2, m_strMaxVal);
  55. DDX_Control(pDX, IDC_SPIN1, m_Spin1);
  56. DDX_Control(pDX, IDC_SPIN2, m_Spin2);
  57. DDX_Control(pDX, COMBO_THRESHOLD_TYPE, m_cbThresholdType);
  58. DDX_Text(pDX, TX_LEFT, m_strLeft);
  59. DDX_Text(pDX, TX_TOP, m_strTop);
  60. DDX_Text(pDX, TX_RIGHT, m_strRight);
  61. DDX_Text(pDX, TX_BOTTOM, m_strBottom);
  62. DDX_Radio(pDX, RADIO_NONE, m_nRadio);
  63. }
  64. // 该函数,只用于Pictrue Control控件中,在Static不适合;
  65. // static text控件要使用,必须先GetDlgItem(IDC_MY_PIC)->ModifyStyle( SS_TYPEMASK, SS_OWNERDRAW );
  66. void CThresholdToolsDlg::DrawMat(Mat & img, UINT uId)
  67. {
  68. if (img.data == NULL)
  69. return;
  70. CRect rc;
  71. Mat imgTmp;
  72. // 获取控件大小;
  73. GetDlgItem(uId)->GetClientRect(&rc);
  74. // 按控件大小,缩小或放大图片;
  75. cv::resize(img, imgTmp, cv::Size(rc.Width(), rc.Height()));
  76. // 转换格式;
  77. switch (imgTmp.channels())
  78. {
  79. case 1:
  80. cv::cvtColor(imgTmp, imgTmp, COLOR_GRAY2BGRA);
  81. break;
  82. case 3:
  83. cv::cvtColor(imgTmp, imgTmp, COLOR_BGR2BGRA);
  84. break;
  85. default:
  86. break;
  87. }
  88. int pixelBytes = imgTmp.channels()*(imgTmp.depth() + 1); // 计算一个像素多少个字节
  89. // 制作bitmapinfo(数据头);
  90. BITMAPINFO bitInfo;
  91. bitInfo.bmiHeader.biBitCount = 8 * pixelBytes;
  92. bitInfo.bmiHeader.biWidth = imgTmp.cols;
  93. bitInfo.bmiHeader.biHeight = -imgTmp.rows;
  94. bitInfo.bmiHeader.biPlanes = 1;
  95. bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  96. bitInfo.bmiHeader.biCompression = BI_RGB;
  97. bitInfo.bmiHeader.biClrImportant = 0;
  98. bitInfo.bmiHeader.biClrUsed = 0;
  99. bitInfo.bmiHeader.biSizeImage = 0;
  100. bitInfo.bmiHeader.biXPelsPerMeter = 0;
  101. bitInfo.bmiHeader.biYPelsPerMeter = 0;
  102. // 双缓存;
  103. CDC *pDC = GetDlgItem(uId)->GetDC();
  104. CDC MemDC; //首先定义一个显示设备对象
  105. CBitmap MemBitmap;//定义一个位图对象
  106. //随后建立与屏幕显示兼容的内存显示设备
  107. MemDC.CreateCompatibleDC(NULL);
  108. //这时还不能绘图,因为没有地方画 ^_^
  109. //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
  110. MemBitmap.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
  111. //将位图选入到内存显示设备中
  112. //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
  113. CBitmap *pOldBit = MemDC.SelectObject(&MemBitmap);
  114. //先用背景色将位图清除干净,这里我用的是白色作为背景
  115. //你也可以用自己应该用的颜色
  116. MemDC.FillSolidRect(0, 0, rc.Width(), rc.Height(), RGB(255, 255, 255));
  117. // Mat.data + bitmap数据头 -> MFC
  118. int nRet = ::StretchDIBits(
  119. MemDC,
  120. 0, 0, rc.Width(), rc.Height(),
  121. 0, 0, rc.Width(), rc.Height(),
  122. imgTmp.data,
  123. &bitInfo,
  124. DIB_RGB_COLORS,
  125. SRCCOPY
  126. );
  127. //将内存中的图拷贝到屏幕上进行显示
  128. pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &MemDC, 0, 0, SRCCOPY);
  129. //绘图完成后的清理
  130. MemBitmap.DeleteObject();
  131. MemDC.DeleteDC();
  132. ReleaseDC(pDC);
  133. }
  134. void CThresholdToolsDlg::RefreshCanvas()
  135. {
  136. CRect rc;
  137. GetDlgItem(IDC_IMG)->GetWindowRect(&rc);
  138. ScreenToClient(&rc);
  139. InvalidateRect(rc, FALSE);//True会闪烁;
  140. }
  141. BOOL CThresholdToolsDlg::ImgThreshold(long nThresholdVal, long nMaxThresholdVal)
  142. {
  143. GetROI();
  144. if (m_ImgROI.data == NULL)
  145. return FALSE;
  146. int nCurSel = m_cbThresholdType.GetCurSel();
  147. if (nCurSel == CB_ERR)
  148. return FALSE;
  149. switch (nCurSel)
  150. {
  151. case 0:
  152. {
  153. // 赋值效果图;
  154. m_pRenderings = &m_ImgShow;
  155. // 刷新画布区域;
  156. RefreshCanvas();
  157. }
  158. break;
  159. case 1://全局阀值;
  160. {
  161. // 转成灰阶图;
  162. cvtColor(m_ImgROI, m_ImgThreshold, COLOR_BGR2GRAY);
  163. // 再高斯模糊处理(滤波);
  164. GaussianBlur(m_ImgThreshold, m_ImgThreshold, Size(5, 5), 0, 0);
  165. // 二值化;//全局化指定的阀值与返回值相等;
  166. double dRetVal = threshold(m_ImgThreshold, m_ImgThreshold, nThresholdVal, nMaxThresholdVal, THRESH_BINARY);
  167. // 赋值效果对象;
  168. //m_pRenderings = &m_ImgThreshold;
  169. // ROI为三通道,所以必须将灰度转回BGR格式,copyTo才有效;
  170. cvtColor(m_ImgThreshold, m_ImgROI, COLOR_GRAY2BGR);
  171. // 将二值图复制ROI上;
  172. //m_ImgThreshold.copyTo(m_ImgROI);
  173. // 赋值效果图;
  174. m_pRenderings = &m_ImgShow;
  175. // 刷新画布区域;
  176. RefreshCanvas();
  177. }
  178. break;
  179. case 2://自适应阀值;
  180. {
  181. // 转成灰阶图;
  182. cvtColor(m_ImgROI, m_ImgThreshold, COLOR_BGR2GRAY);
  183. // 再高斯模糊处理(滤波);
  184. GaussianBlur(m_ImgThreshold, m_ImgThreshold, Size(3, 3), 0, 0);
  185. // 自适应阀值;
  186. medianBlur(m_ImgThreshold, m_ImgThreshold, 3);
  187. // 局部二值化;//blocksize一般取3、5、7
  188. adaptiveThreshold(m_ImgThreshold, m_ImgThreshold, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, 4.5);
  189. // 赋值效果对象;
  190. //m_pRenderings = &m_ImgThreshold;
  191. // ROI为三通道,所以必须将灰度转回BGR格式,copyTo才有效;
  192. cvtColor(m_ImgThreshold, m_ImgROI, COLOR_GRAY2BGR);
  193. // 将二值图复制ROI上;
  194. //m_ImgThreshold.copyTo(m_ImgROI);
  195. // 赋值效果图;
  196. m_pRenderings = &m_ImgShow;
  197. // 刷新画布区域;
  198. RefreshCanvas();
  199. }
  200. break;
  201. case 3:// otsu阀值;
  202. {
  203. cvtColor(m_ImgROI, m_ImgThreshold, COLOR_BGR2GRAY);
  204. // 高斯模糊;
  205. GaussianBlur(m_ImgThreshold, m_ImgThreshold, Size(3, 3), 0, 0);
  206. #if 0
  207. // otus;//阀值必须为0;
  208. Mat tempImg;
  209. m_ImgThreshold.copyTo(tempImg);
  210. double dRetVal = threshold(m_ImgThreshold, tempImg, nThresholdVal, nMaxThresholdVal, THRESH_BINARY | THRESH_OTSU);
  211. //TRACE1("当前阀值:%lf\n", dRetVal);
  212. threshold(m_ImgThreshold, m_ImgThreshold, dRetVal, nMaxThresholdVal, THRESH_BINARY);
  213. #else
  214. threshold(m_ImgThreshold, m_ImgThreshold, nThresholdVal, nMaxThresholdVal, THRESH_BINARY | THRESH_OTSU);
  215. #endif
  216. // 赋值效果对象;
  217. //m_pRenderings = &m_ImgThreshold;
  218. // ROI为三通道,所以必须将灰度转回BGR格式,copyTo才有效;
  219. cvtColor(m_ImgThreshold, m_ImgROI, COLOR_GRAY2BGR);
  220. // 将二值图复制ROI上;
  221. //m_ImgThreshold.copyTo(m_ImgROI);
  222. // 赋值效果图;
  223. m_pRenderings = &m_ImgShow;
  224. // 刷新画布区域;
  225. RefreshCanvas();
  226. }
  227. break;
  228. default:
  229. break;
  230. }
  231. if (m_ImgThreshold.data) {
  232. // 查找轮廓;
  233. m_contours.clear();
  234. m_hierarchy.clear();
  235. BOOL bCheck = ((CButton*)GetDlgItem(IDC_CHECK3))->GetCheck();
  236. if (bCheck == TRUE)
  237. {
  238. // 所有轮廓,内外轮廓分等级;
  239. findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
  240. // 所有轮廓,内外轮廓不分等级,独立;
  241. //findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
  242. }
  243. else
  244. {
  245. // RETR_EXTERNAL=只检索最外面的轮廓;
  246. findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
  247. }
  248. }
  249. return TRUE;
  250. }
  251. BOOL CThresholdToolsDlg::DrawContours(BOOL bPerimeter,long nMinPerimeter, long nMaxPerimeter, BOOL bArea,long nMinArea, long nMaxArea)
  252. {
  253. //if ( m_ImgThreshold.data == NULL)
  254. // return FALSE;
  255. //
  256. //// 查找轮廓;
  257. //m_contours.clear();
  258. //m_hierarchy.clear();
  259. //BOOL bCheck = ((CButton*)GetDlgItem(IDC_CHECK3))->GetCheck();
  260. //if (bCheck == TRUE)
  261. //{
  262. // // 所有轮廓,内外轮廓分等级;
  263. // findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
  264. // // 所有轮廓,内外轮廓不分等级,独立;
  265. // //findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
  266. //}
  267. //else
  268. //{
  269. // // RETR_EXTERNAL=只检索最外面的轮廓;
  270. // findContours(m_ImgThreshold, m_contours, m_hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
  271. //}
  272. // 过滤不符合要求的轮廓;
  273. int i = 0;
  274. GetROI();
  275. m_ImgContours = m_ImgROI.clone();
  276. vector<vector<Point>>::iterator it = m_contours.begin();
  277. for ( ; it != m_contours.end(); it++,i++)
  278. {
  279. if (bPerimeter && !bArea)
  280. {
  281. if (arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter)
  282. continue;
  283. }
  284. else if (!bPerimeter && bArea)
  285. {
  286. if (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea)
  287. continue;
  288. }
  289. else if (bArea && bPerimeter)
  290. {
  291. if ((arcLength(*it, true) < nMinPerimeter || arcLength(*it, true) > nMaxPerimeter) || (contourArea(*it) < nMinArea || contourArea(*it) > nMaxArea))
  292. continue;
  293. }
  294. // 填充轮廓;
  295. Scalar color = Scalar(rand() % 255, rand() % 255, rand() % 255);
  296. drawContours(m_ImgContours, m_contours, i, color, CV_FILLED, 8, m_hierarchy);
  297. }
  298. m_ImgContours.copyTo(m_ImgROI);
  299. m_pRenderings = &m_ImgShow;
  300. // 刷新画布区域;
  301. RefreshCanvas();
  302. return TRUE;
  303. }
  304. void CThresholdToolsDlg::GetPointInfo(CPoint pt, long &nPerimeter, long &nArea, Rect &rc)
  305. {
  306. long a1 = 0, p1 = 0;
  307. vector<vector<Point>>::iterator it = m_contours.begin();
  308. BOOL bCheck = ((CButton*)GetDlgItem(IDC_CHECK3))->GetCheck();
  309. int left = GetDlgItemInt(TX_LEFT);
  310. int top = GetDlgItemInt(TX_TOP);
  311. for (; it != m_contours.end(); it++)
  312. {
  313. // 检测点是否在轮廓内;
  314. if (pointPolygonTest(*it, cv::Point(pt.x, pt.y), false) == 1)
  315. {
  316. a1 = contourArea(*it);
  317. p1 = arcLength(*it, true);
  318. if (bCheck == FALSE)
  319. {// 外轮廓;
  320. nArea = a1, nPerimeter = p1;
  321. #if 1
  322. // 计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的;
  323. rc = boundingRect(*it);
  324. rc.x = rc.x + left;
  325. rc.y = rc.y + top;
  326. #else
  327. vector<Point> contours_poly;
  328. // 把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合
  329. approxPolyDP(*it, contours_poly, 3, TRUE);
  330. // 计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的;
  331. rc = boundingRect(contours_poly);
  332. // minAreaRect,minEnclosingTriangle,minEnclosingCircle
  333. RotatedRect rc_ = minAreaRect(contours_poly);//有角度的矩形;
  334. #endif
  335. break;
  336. }
  337. else
  338. {// 内轮廓;
  339. if (nArea > a1)
  340. nArea = a1;
  341. if (nPerimeter > p1)
  342. nPerimeter = p1;
  343. #if 1
  344. // 计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的;
  345. rc = boundingRect(*it);
  346. rc.x = rc.x + left;
  347. rc.y = rc.y + top;
  348. #else
  349. vector<Point> contours_poly;
  350. // 把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合
  351. approxPolyDP(*it, contours_poly, 3, TRUE);
  352. // 计算轮廓的垂直边界最小矩形,矩形是与图像上下边界平行的;
  353. rc = boundingRect(contours_poly);
  354. // minAreaRect,minEnclosingTriangle,minEnclosingCircle
  355. RotatedRect rc_ = minAreaRect(contours_poly);//有角度的矩形;
  356. #endif
  357. }
  358. }
  359. }
  360. }
  361. CPoint CThresholdToolsDlg::WndPt2ImgPt(CPoint WndPt)
  362. {
  363. // 1.屏幕坐标转成窗口坐标;
  364. //ScreenToClient(&WndPt);
  365. // 2.窗口坐标转成控件坐标;
  366. CRect rcWnd;
  367. CWnd *pWnd = GetDlgItem(IDC_IMG);
  368. pWnd->GetWindowRect(&rcWnd);
  369. ScreenToClient(&rcWnd);
  370. WndPt.x -= rcWnd.left;
  371. WndPt.y -= rcWnd.top;
  372. // 3.将控件坐标转成图像坐标;
  373. // 计算出png原图缩放显示到窗口的缩放比例;
  374. float fScalex = (float)rcWnd.Width() / m_Img.cols;
  375. float fScaley = (float)rcWnd.Height() / m_Img.rows;
  376. #if 0
  377. CString str;
  378. str.Format(_T("控件坐标点:x=%d,y=%d, scalex=%lf=%ld,%ld, scaley=%lf=%ld,%ld\n"),
  379. WndPt.x, WndPt.y, fScalex, rcWnd.Width() , m_Img.cols, fScaley, rcWnd.Height(), m_Img.rows);
  380. OutputDebugString(str);
  381. #endif
  382. // 3.再将窗口点缩放到PNG原图比例;
  383. WndPt.x /= fScalex;
  384. WndPt.y /= fScaley;
  385. return WndPt;
  386. }
  387. void CThresholdToolsDlg::GetROI()
  388. {
  389. if ( m_ImgShow.data)
  390. {
  391. m_ImgShow.release();
  392. }
  393. if ( m_ImgROI.data)
  394. {
  395. m_ImgROI.release();
  396. }
  397. m_Img.copyTo(m_ImgShow);
  398. m_ImgROI = m_ImgShow([&]()-> Rect {
  399. long left = GetDlgItemInt(TX_LEFT);
  400. long top = GetDlgItemInt(TX_TOP);
  401. long right = GetDlgItemInt(TX_RIGHT);
  402. long bottom = GetDlgItemInt(TX_BOTTOM);
  403. if (left < 0)
  404. left = 0;
  405. if (top < 0)
  406. top = 0;
  407. if (top > m_Img.rows)
  408. top = m_Img.rows;
  409. if (left > m_Img.cols)
  410. left = m_Img.cols;
  411. left = left > m_Img.cols ? 0 : left;
  412. top = top > m_Img.rows ? 0 : top;
  413. // 注意是x,y,w=cols,h=rows
  414. return Rect( left, top, right - left, bottom - top);
  415. }());
  416. }
  417. BEGIN_MESSAGE_MAP(CThresholdToolsDlg, CDialogEx)
  418. ON_WM_SYSCOMMAND()
  419. ON_WM_PAINT()
  420. ON_WM_QUERYDRAGICON()
  421. ON_BN_CLICKED(BTN_OPENIMG, &CThresholdToolsDlg::OnBnClickedOpenimg)
  422. ON_WM_SIZE()
  423. ON_WM_HSCROLL()
  424. ON_BN_CLICKED(IDOK, &CThresholdToolsDlg::OnBnClickedOk)
  425. ON_BN_CLICKED(IDCANCEL, &CThresholdToolsDlg::OnBnClickedCancel)
  426. ON_BN_CLICKED(BTN_RESET, &CThresholdToolsDlg::OnBnClickedReset)
  427. ON_BN_CLICKED(IDC_BUTTON2, &CThresholdToolsDlg::OnBnClickedButton2)
  428. ON_BN_CLICKED(IDC_CHECK1, &CThresholdToolsDlg::OnBnClickedCheck1)
  429. ON_BN_CLICKED(IDC_CHECK2, &CThresholdToolsDlg::OnBnClickedCheck2)
  430. ON_EN_CHANGE(TX_Perimeter, &CThresholdToolsDlg::OnEnChangePerimeter)
  431. ON_EN_CHANGE(TX_Square, &CThresholdToolsDlg::OnEnChangeSquare)
  432. ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN1, &CThresholdToolsDlg::OnDeltaposSpin1)
  433. ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN2, &CThresholdToolsDlg::OnDeltaposSpin2)
  434. ON_EN_CHANGE(TX_Perimeter2, &CThresholdToolsDlg::OnEnChangePerimeter2)
  435. ON_EN_CHANGE(TX_Square2, &CThresholdToolsDlg::OnEnChangeSquare2)
  436. ON_WM_MOUSEWHEEL()
  437. ON_WM_MOUSEMOVE()
  438. ON_BN_CLICKED(IDC_CHECK3, &CThresholdToolsDlg::OnBnClickedCheck3)
  439. ON_CBN_SELCHANGE(COMBO_THRESHOLD_TYPE, &CThresholdToolsDlg::OnCbnSelchangeThresholdType)
  440. ON_EN_CHANGE(TX_LEFT, &CThresholdToolsDlg::OnEnChangeLeft)
  441. ON_EN_CHANGE(TX_TOP, &CThresholdToolsDlg::OnEnChangeTop)
  442. ON_EN_CHANGE(TX_RIGHT, &CThresholdToolsDlg::OnEnChangeRight)
  443. ON_EN_CHANGE(TX_BOTTOM, &CThresholdToolsDlg::OnEnChangeBottom)
  444. ON_BN_CLICKED(BTN_PREVE, &CThresholdToolsDlg::OnBnClickedPreve)
  445. ON_BN_CLICKED(BTN_NEXT, &CThresholdToolsDlg::OnBnClickedNext)
  446. ON_BN_CLICKED(RADIO_NONE, &CThresholdToolsDlg::OnBnClickedThreshold)
  447. ON_BN_CLICKED(RADIO_THRESHOLD, &CThresholdToolsDlg::OnBnClickedThreshold)
  448. ON_BN_CLICKED(RADIO_FILLCONTOUR, &CThresholdToolsDlg::OnBnClickedThreshold)
  449. ON_BN_CLICKED(RADIO_TEMP, &CThresholdToolsDlg::OnBnClickedThreshold)
  450. ON_BN_CLICKED(BTN_OPEN_TEMP, &CThresholdToolsDlg::OnBnClickedOpenTemp)
  451. ON_BN_CLICKED(BTN_FIND_TEMP, &CThresholdToolsDlg::OnBnClickedFindTemp)
  452. END_MESSAGE_MAP()
  453. // CThresholdToolsDlg 消息处理程序
  454. BOOL CThresholdToolsDlg::OnInitDialog()
  455. {
  456. CDialogEx::OnInitDialog();
  457. // 将“关于...”菜单项添加到系统菜单中。
  458. // IDM_ABOUTBOX 必须在系统命令范围内。
  459. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  460. ASSERT(IDM_ABOUTBOX < 0xF000);
  461. CMenu* pSysMenu = GetSystemMenu(FALSE);
  462. if (pSysMenu != nullptr)
  463. {
  464. BOOL bNameValid;
  465. CString strAboutMenu;
  466. bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
  467. ASSERT(bNameValid);
  468. if (!strAboutMenu.IsEmpty())
  469. {
  470. pSysMenu->AppendMenu(MF_SEPARATOR);
  471. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  472. }
  473. }
  474. // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
  475. // 执行此操作
  476. SetIcon(m_hIcon, TRUE); // 设置大图标
  477. SetIcon(m_hIcon, FALSE); // 设置小图标
  478. SetDlgItemText(TX_Perimeter, _T("500"));
  479. SetDlgItemText(TX_Square, _T("500"));
  480. SetDlgItemText(TX_Perimeter2, _T("1000"));
  481. SetDlgItemText(TX_Square2, _T("1000"));
  482. #if 0
  483. m_Img = imread("E:\\IMCapture\\AVerCapSDK.png");
  484. m_img_bak = m_Img.clone();
  485. DrawMat(m_Img, IDC_IMG);
  486. #endif
  487. GetClientRect(&m_WndRect);
  488. // 将static控件样式修改;
  489. GetDlgItem(IDC_IMG)->ModifyStyle(SS_TYPEMASK, SS_OWNERDRAW);
  490. // 设置范围;
  491. m_slider.SetRange(0, 255);
  492. // 每10个值设置一个刻度;
  493. m_slider.SetTicFreq(10);
  494. // 设置滑动刻度;
  495. m_slider.SetPageSize(1);
  496. // 设置全局阀值为默认;
  497. m_cbThresholdType.SetCurSel(0);
  498. //m_Spin1.SetRange(100000, 0);
  499. //m_Spin2.SetRange(100000, 0);
  500. // m_Spin1.SetRange(0, 100000);
  501. // m_Spin2.SetRange(0, 100000);
  502. return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
  503. }
  504. void CThresholdToolsDlg::OnSysCommand(UINT nID, LPARAM lParam)
  505. {
  506. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  507. {
  508. CAboutDlg dlgAbout;
  509. dlgAbout.DoModal();
  510. }
  511. else
  512. {
  513. CDialogEx::OnSysCommand(nID, lParam);
  514. }
  515. }
  516. // 如果向对话框添加最小化按钮,则需要下面的代码
  517. // 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
  518. // 这将由框架自动完成。
  519. void CThresholdToolsDlg::OnPaint()
  520. {
  521. if (IsIconic())
  522. {
  523. CPaintDC dc(this); // 用于绘制的设备上下文
  524. SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  525. // 使图标在工作区矩形中居中
  526. int cxIcon = GetSystemMetrics(SM_CXICON);
  527. int cyIcon = GetSystemMetrics(SM_CYICON);
  528. CRect rect;
  529. GetClientRect(&rect);
  530. int x = (rect.Width() - cxIcon + 1) / 2;
  531. int y = (rect.Height() - cyIcon + 1) / 2;
  532. // 绘制图标
  533. dc.DrawIcon(x, y, m_hIcon);
  534. }
  535. else
  536. {
  537. CDialogEx::OnPaint();
  538. // 绘图;
  539. if (m_pRenderings)
  540. {
  541. DrawMat(*m_pRenderings, IDC_IMG);
  542. //DrawMat(m_ImgShow, IDC_IMG);
  543. }
  544. // 模板图片;
  545. if ( m_ImgTemp.data)
  546. {
  547. DrawMat(m_ImgTemp, IDC_TEMP);
  548. }
  549. }
  550. }
  551. //当用户拖动最小化窗口时系统调用此函数取得光标
  552. //显示。
  553. HCURSOR CThresholdToolsDlg::OnQueryDragIcon()
  554. {
  555. return static_cast<HCURSOR>(m_hIcon);
  556. }
  557. void CThresholdToolsDlg::OnBnClickedOpenimg() // 打开图片;
  558. {
  559. // TODO: 在此添加控件通知处理程序代码
  560. CString strFindFile = _T("");
  561. CString strFilters = _T("图片(*.jpg;*.jpeg;*.png;*.bmp;)||所有文件 (*.*)|*.*||");
  562. CString strDeftExt = _T("default Files (*.png)");
  563. CString strTitle = _T("请选择要取阀值的图片");
  564. DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ENABLESIZING;
  565. CFileDialog dlg(TRUE, strDeftExt, NULL, dwFlags, strFilters, NULL);
  566. dlg.m_ofn.lpstrTitle = strTitle; // 显示的标题, 应该做成参数传入;
  567. dlg.m_ofn.lpstrInitialDir = NULL; // 默认打开的文件夹, 应该做成参数传入;
  568. // 显示文件对话框,获得文件名集合;
  569. if (dlg.DoModal() == IDCANCEL)
  570. return;
  571. CString strFiles = dlg.GetPathName();
  572. CString strPath = dlg.GetFolderPath();
  573. m_files.clear();
  574. filehelpImpl fhelp;
  575. fhelp.getfiles_findout_subfolder(strPath.GetString(), _T("*.png|*.jpg|*.bmp"), &m_files);
  576. OpenImg(strFiles.GetString(), TRUE);
  577. m_curIndex = GetFileIndex(strFiles.GetString(), m_files);
  578. }
  579. void CThresholdToolsDlg::OnSize(UINT nType, int cx, int cy)
  580. {
  581. return CDialogEx::OnSize(nType, cx, cy);
  582. // 获取控件句柄;
  583. CWnd *pWnd = GetDlgItem(IDC_IMG);
  584. if ( pWnd )
  585. {
  586. CRect rcContrl;
  587. pWnd->GetWindowRect(&rcContrl);
  588. ScreenToClient(&rcContrl);
  589. rcContrl.right = cx - 20;
  590. rcContrl.bottom = cy - 50;
  591. pWnd->MoveWindow(rcContrl);
  592. }
  593. }
  594. void CThresholdToolsDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  595. {
  596. // TODO: 在此添加消息处理程序代码和/或调用默认值
  597. if ((&m_slider) == (CSliderCtrl *)pScrollBar) // mSlider 为你的slider控件
  598. {
  599. // 获取当前刻度;
  600. long lVal = m_slider.GetPos();
  601. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  602. // 图像二值化;
  603. if ( ImgThreshold(lVal, lMaxVal) )
  604. {
  605. CString str;
  606. str.Format(_T("当前值:%ld"), lVal);
  607. SetWindowText(str);
  608. }
  609. m_bPerimeter = ((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck();
  610. if (m_nRadio != 2)
  611. return;
  612. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  613. long nSquare = GetDlgItemInt(TX_Square);
  614. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  615. long nSquare2 = GetDlgItemInt(TX_Square2);
  616. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  617. }
  618. CDialogEx::OnHScroll(nSBCode, nPos, pScrollBar);
  619. }
  620. void CThresholdToolsDlg::OnBnClickedOk()
  621. {
  622. // TODO: 在此添加控件通知处理程序代码
  623. CDialogEx::OnOK();
  624. }
  625. void CThresholdToolsDlg::OnBnClickedCancel()
  626. {
  627. // TODO: 在此添加控件通知处理程序代码
  628. CDialogEx::OnCancel();
  629. }
  630. void CThresholdToolsDlg::OnBnClickedReset() // 复位;
  631. {
  632. m_slider.SetPos(0);
  633. m_Img.copyTo(m_ImgShow);
  634. m_pRenderings = &m_ImgShow;
  635. // 刷新画布;
  636. RefreshCanvas();
  637. }
  638. void CThresholdToolsDlg::OnBnClickedButton2() // 轮廓;
  639. {
  640. // TODO: 在此添加控件通知处理程序代码
  641. // 获取当前刻度;
  642. long lVal = m_slider.GetPos();
  643. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  644. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  645. long nSquare = GetDlgItemInt(TX_Square);
  646. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  647. long nSquare2 = GetDlgItemInt(TX_Square2);
  648. if ( !m_bThreshold)
  649. {
  650. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  651. SetDlgItemText(IDC_BUTTON2, _T("二值化"));
  652. }
  653. else
  654. {
  655. GetROI();
  656. if (m_ImgThreshold.data)
  657. {
  658. cvtColor(m_ImgThreshold, m_ImgROI, COLOR_GRAY2BGR);
  659. m_ImgThreshold.copyTo(m_ImgROI);
  660. m_pRenderings = &m_ImgShow;
  661. }
  662. // 刷新;
  663. RefreshCanvas();
  664. SetDlgItemText(IDC_BUTTON2, _T("轮廓"));
  665. }
  666. m_bThreshold = !m_bThreshold;
  667. }
  668. void CThresholdToolsDlg::OnBnClickedCheck1() // 周长;
  669. {
  670. m_bPerimeter = ((CButton*)GetDlgItem(IDC_CHECK1))->GetCheck();
  671. if (m_nRadio != 2)
  672. return;
  673. long lVal = m_slider.GetPos();
  674. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  675. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  676. long nSquare = GetDlgItemInt(TX_Square);
  677. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  678. long nSquare2 = GetDlgItemInt(TX_Square2);
  679. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  680. }
  681. void CThresholdToolsDlg::OnBnClickedCheck2() // 面积;
  682. {
  683. m_bSquare = ((CButton*)GetDlgItem(IDC_CHECK2))->GetCheck();
  684. if (m_nRadio != 2)
  685. return;
  686. long lVal = m_slider.GetPos();
  687. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  688. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  689. long nSquare = GetDlgItemInt(TX_Square);
  690. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  691. long nSquare2 = GetDlgItemInt(TX_Square2);
  692. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  693. }
  694. void CThresholdToolsDlg::OnEnChangePerimeter()
  695. {
  696. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  697. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  698. // 函数并调用 CRichEditCtrl().SetEventMask(),
  699. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  700. if ( m_nRadio == 2 )
  701. {
  702. long lVal = m_slider.GetPos();
  703. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  704. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  705. long nSquare = GetDlgItemInt(TX_Square);
  706. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  707. long nSquare2 = GetDlgItemInt(TX_Square2);
  708. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  709. }
  710. // TODO: 在此添加控件通知处理程序代码
  711. }
  712. void CThresholdToolsDlg::OnEnChangeSquare()
  713. {
  714. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  715. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  716. // 函数并调用 CRichEditCtrl().SetEventMask(),
  717. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  718. if (m_nRadio == 2)
  719. {
  720. long lVal = m_slider.GetPos();
  721. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  722. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  723. long nSquare = GetDlgItemInt(TX_Square);
  724. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  725. long nSquare2 = GetDlgItemInt(TX_Square2);
  726. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  727. }
  728. // TODO: 在此添加控件通知处理程序代码
  729. }
  730. void CThresholdToolsDlg::OnDeltaposSpin1(NMHDR *pNMHDR, LRESULT *pResult)
  731. {
  732. LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
  733. // TODO: 在此添加控件通知处理程序代码
  734. long val = GetDlgItemInt(TX_Perimeter);
  735. if ( pNMUpDown->iDelta == 1) // 向下;
  736. {
  737. val--;
  738. }
  739. else if (pNMUpDown->iDelta == -1)// 向上;
  740. {
  741. val++;
  742. }
  743. *pResult = 0;
  744. SetDlgItemInt(TX_Perimeter, val);
  745. }
  746. void CThresholdToolsDlg::OnDeltaposSpin2(NMHDR *pNMHDR, LRESULT *pResult)
  747. {
  748. LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR);
  749. // TODO: 在此添加控件通知处理程序代码
  750. long val = GetDlgItemInt(TX_Square);
  751. if (pNMUpDown->iDelta == 1) // 向下;
  752. {
  753. val--;
  754. }
  755. else if (pNMUpDown->iDelta == -1)// 向上;
  756. {
  757. val++;
  758. }
  759. *pResult = 0;
  760. SetDlgItemInt(TX_Square, val);
  761. }
  762. void CThresholdToolsDlg::OnEnChangePerimeter2()
  763. {
  764. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  765. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  766. // 函数并调用 CRichEditCtrl().SetEventMask(),
  767. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  768. if (m_nRadio == 2)
  769. {
  770. long lVal = m_slider.GetPos();
  771. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  772. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  773. long nSquare = GetDlgItemInt(TX_Square);
  774. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  775. long nSquare2 = GetDlgItemInt(TX_Square2);
  776. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  777. }
  778. // TODO: 在此添加控件通知处理程序代码
  779. }
  780. void CThresholdToolsDlg::OnEnChangeSquare2()
  781. {
  782. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  783. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  784. // 函数并调用 CRichEditCtrl().SetEventMask(),
  785. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  786. if (m_nRadio == 2)
  787. {
  788. long lVal = m_slider.GetPos();
  789. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  790. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  791. long nSquare = GetDlgItemInt(TX_Square);
  792. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  793. long nSquare2 = GetDlgItemInt(TX_Square2);
  794. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  795. }
  796. // TODO: 在此添加控件通知处理程序代码
  797. }
  798. BOOL CThresholdToolsDlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  799. {
  800. // TODO: 在此添加消息处理程序代码和/或调用默认值
  801. CWnd *pWnd = GetFocus();
  802. if ( pWnd == GetDlgItem(TX_Perimeter) || pWnd == GetDlgItem(TX_Perimeter2)
  803. || pWnd == GetDlgItem(TX_Square) || pWnd == GetDlgItem(TX_Square2))
  804. {
  805. long nVal = GetDlgItemInt(pWnd->GetDlgCtrlID());
  806. if ( zDelta > 0 )
  807. {//向上滚动;
  808. nVal++;
  809. }
  810. else
  811. {
  812. nVal--;
  813. }
  814. SetDlgItemInt(pWnd->GetDlgCtrlID(), nVal);
  815. }
  816. if (pWnd == GetDlgItem(TX_LEFT) )
  817. {
  818. long nVal = GetDlgItemInt(pWnd->GetDlgCtrlID());
  819. if (zDelta > 0)
  820. {//向上滚动;
  821. if (nVal < m_Img.cols)
  822. nVal++;
  823. }
  824. else
  825. {
  826. if (nVal > 0 )
  827. nVal--;
  828. }
  829. SetDlgItemInt(pWnd->GetDlgCtrlID(), nVal);
  830. }
  831. if ( pWnd == GetDlgItem(TX_TOP))
  832. {
  833. long nVal = GetDlgItemInt(pWnd->GetDlgCtrlID());
  834. if (zDelta > 0)
  835. {//向上滚动;
  836. if (nVal < m_Img.rows)
  837. nVal++;
  838. }
  839. else
  840. {
  841. if (nVal > 0)
  842. nVal--;
  843. }
  844. SetDlgItemInt(pWnd->GetDlgCtrlID(), nVal);
  845. }
  846. if ( pWnd == GetDlgItem(TX_RIGHT) )
  847. {
  848. long nVal = GetDlgItemInt(pWnd->GetDlgCtrlID());
  849. if (zDelta > 0)
  850. {//向上滚动;
  851. if (nVal < m_Img.cols)
  852. nVal++;
  853. }
  854. else
  855. {
  856. if (nVal > 0)
  857. nVal--;
  858. }
  859. SetDlgItemInt(pWnd->GetDlgCtrlID(), nVal);
  860. }
  861. if ( pWnd == GetDlgItem(TX_BOTTOM))
  862. {
  863. long nVal = GetDlgItemInt(pWnd->GetDlgCtrlID());
  864. if (zDelta > 0)
  865. {//向上滚动;
  866. if (nVal < m_Img.rows)
  867. nVal++;
  868. }
  869. else
  870. {
  871. if (nVal > 0)
  872. nVal--;
  873. }
  874. SetDlgItemInt(pWnd->GetDlgCtrlID(), nVal);
  875. }
  876. return CDialogEx::OnMouseWheel(nFlags, zDelta, pt);
  877. }
  878. BOOL CThresholdToolsDlg::PreTranslateMessage(MSG* pMsg)
  879. {
  880. // TODO: 在此添加专用代码和/或调用基类
  881. if (pMsg->message == WM_KEYDOWN)
  882. {
  883. CWnd *pWnd = GetFocus();
  884. if (pWnd == GetDlgItem(TX_Perimeter) || pWnd == GetDlgItem(TX_Perimeter2)
  885. || pWnd == GetDlgItem(TX_Square) || pWnd == GetDlgItem(TX_Square2)
  886. || pWnd == GetDlgItem(TX_LEFT) || pWnd == GetDlgItem(TX_TOP)
  887. || pWnd == GetDlgItem(TX_RIGHT) || pWnd == GetDlgItem(TX_BOTTOM)
  888. )
  889. {
  890. long nVal = GetDlgItemInt(pWnd->GetDlgCtrlID());
  891. if (pMsg->wParam == VK_UP)
  892. {
  893. nVal++;
  894. SetDlgItemInt(pWnd->GetDlgCtrlID(), nVal);
  895. }
  896. else if (pMsg->wParam == VK_DOWN)
  897. {
  898. nVal--;
  899. SetDlgItemInt(pWnd->GetDlgCtrlID(), nVal);
  900. }
  901. }
  902. }
  903. else if (pMsg->message == WM_LBUTTONDOWN)
  904. {
  905. CPoint point;
  906. GetCursorPos(&point);
  907. CRect rcWnd;
  908. CWnd *pWnd = GetDlgItem(IDC_IMG);
  909. pWnd->GetWindowRect(&rcWnd);
  910. if (!PtInRect(&rcWnd, point))
  911. return CDialogEx::PreTranslateMessage(pMsg);
  912. ScreenToClient(&point);
  913. point = WndPt2ImgPt(point);
  914. m_bPress = TRUE;
  915. m_firstPt.x = point.x;
  916. m_firstPt.y = point.y;
  917. long nPerimeter = 100000, nArea = 1000000;
  918. Rect rc;
  919. GetPointInfo(point, nPerimeter, nArea, rc);
  920. if (nPerimeter > 200 || nArea > 1000)
  921. {
  922. CString str;
  923. GetWindowText(str);
  924. int nIndex = str.Find(_T(" \t\t\t"));
  925. str.Format(_T("%s \t\t\t 周长:%ld,面积:%ld\n, 坐标=[%d,%d,%d,%d]"), (nIndex == -1 ? str : str.Left(nIndex)), nPerimeter, nArea, rc.x, rc.y, rc.x+rc.width, rc.y+rc.height);
  926. SetWindowText(str);
  927. }
  928. }
  929. else if (pMsg->message == WM_LBUTTONUP)
  930. {
  931. if (m_bPress)
  932. {
  933. m_bPress = FALSE;
  934. // 最后的点;
  935. CPoint point;
  936. GetCursorPos(&point);
  937. CRect rcWnd;
  938. CWnd *pWnd = GetDlgItem(IDC_IMG);
  939. pWnd->GetWindowRect(&rcWnd);
  940. if (!PtInRect(&rcWnd, point))
  941. return CDialogEx::PreTranslateMessage(pMsg);
  942. ScreenToClient(&point);
  943. point = WndPt2ImgPt(point);
  944. m_lastPt.x = point.x;
  945. m_lastPt.y = point.y;
  946. SetDlgItemInt(TX_LEFT, m_firstPt.x);
  947. SetDlgItemInt(TX_TOP, m_firstPt.y);
  948. SetDlgItemInt(TX_RIGHT, m_lastPt.x);
  949. SetDlgItemInt(TX_BOTTOM, m_lastPt.y);
  950. }
  951. }
  952. return CDialogEx::PreTranslateMessage(pMsg);
  953. }
  954. void CThresholdToolsDlg::OnMouseMove(UINT nFlags, CPoint point)
  955. {
  956. // TODO: 在此添加消息处理程序代码和/或调用默认值
  957. #if 0
  958. if (m_contours.size())
  959. {
  960. // 坐标转换;
  961. CString str;
  962. point = WndPt2ImgPt(point);
  963. long nPerimeter = 0, nArea = 0;
  964. GetPointInfo(point, nPerimeter, nArea);
  965. if (nPerimeter > 200 || nArea > 1000)
  966. {
  967. #if _DEBUG
  968. str.Format(_T("周长:%ld,面积:%ld\n"), nPerimeter, nArea);
  969. OutputDebugString(str);
  970. #endif
  971. }
  972. }
  973. #endif
  974. if ( m_bPress )
  975. {
  976. if (m_ImgShow.data)
  977. m_ImgShow.release();
  978. CPoint point;
  979. GetCursorPos(&point);
  980. CRect rcWnd;
  981. CWnd *pWnd = GetDlgItem(IDC_IMG);
  982. pWnd->GetWindowRect(&rcWnd);
  983. if (!PtInRect(&rcWnd, point))
  984. return CDialogEx::OnMouseMove(nFlags, point);
  985. ScreenToClient(&point);
  986. point = WndPt2ImgPt(point);
  987. m_lastPt.x = point.x;
  988. m_lastPt.y = point.y;
  989. m_Img.copyTo(m_ImgShow);
  990. rectangle(m_ImgShow, m_firstPt, Point(m_lastPt.x, m_lastPt.y), Scalar(rand() % 255, rand() % 255, rand() % 255), 1, CV_AA, 0);
  991. m_pRenderings = &m_ImgShow;
  992. SetWindowText([&]()->CString {
  993. CString str;
  994. str.Format(_T("坐标=[%d,%d,%d,%d]"), m_firstPt.x, m_firstPt.y, point.x, point.y);
  995. return str;
  996. }());
  997. RefreshCanvas();
  998. }
  999. CDialogEx::OnMouseMove(nFlags, point);
  1000. }
  1001. void CThresholdToolsDlg::OnBnClickedCheck3() // 内轮廓;
  1002. {
  1003. int nPos = m_slider.GetPos();
  1004. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  1005. long nSquare = GetDlgItemInt(TX_Square);
  1006. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  1007. long nSquare2 = GetDlgItemInt(TX_Square2);
  1008. if (nPos != 0)
  1009. {
  1010. // 二值化;
  1011. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1012. ImgThreshold(nPos, lMaxVal);
  1013. if (m_nRadio == 2)
  1014. {
  1015. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1016. }
  1017. else
  1018. {
  1019. // 刷新;
  1020. RefreshCanvas();
  1021. }
  1022. }
  1023. else
  1024. {
  1025. int nCurSel = m_cbThresholdType.GetCurSel();
  1026. if (nCurSel != 0)
  1027. {
  1028. // 二值化;
  1029. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1030. ImgThreshold(nPos, lMaxVal);
  1031. if (m_nRadio == 2)
  1032. {
  1033. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1034. }
  1035. else
  1036. {
  1037. // 刷新;
  1038. RefreshCanvas();
  1039. }
  1040. }
  1041. else
  1042. {
  1043. m_pRenderings = &m_ImgShow;
  1044. }
  1045. RefreshCanvas();
  1046. }
  1047. }
  1048. void CThresholdToolsDlg::OnCbnSelchangeThresholdType()
  1049. {
  1050. // TODO: 在此添加控件通知处理程序代码
  1051. int nPos = m_slider.GetPos();
  1052. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  1053. long nSquare = GetDlgItemInt(TX_Square);
  1054. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  1055. long nSquare2 = GetDlgItemInt(TX_Square2);
  1056. if (nPos != 0)
  1057. {
  1058. // 二值化;
  1059. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1060. ImgThreshold(nPos, lMaxVal);
  1061. if (m_nRadio == 2)
  1062. {
  1063. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1064. }
  1065. else
  1066. {
  1067. // 刷新;
  1068. RefreshCanvas();
  1069. }
  1070. }
  1071. else
  1072. {
  1073. int nCurSel = m_cbThresholdType.GetCurSel();
  1074. if (nCurSel != 0)
  1075. {
  1076. // 二值化;
  1077. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1078. ImgThreshold(nPos, lMaxVal);
  1079. if (m_nRadio == 2)
  1080. {
  1081. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1082. }
  1083. else
  1084. {
  1085. // 刷新;
  1086. RefreshCanvas();
  1087. }
  1088. }
  1089. else
  1090. {
  1091. m_pRenderings = &m_ImgShow;
  1092. }
  1093. RefreshCanvas();
  1094. }
  1095. }
  1096. void CThresholdToolsDlg::OnEnChangeLeft()
  1097. {
  1098. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  1099. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  1100. // 函数并调用 CRichEditCtrl().SetEventMask(),
  1101. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  1102. m_Img.copyTo(m_ImgShow);
  1103. int nPos = m_slider.GetPos();
  1104. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  1105. long nSquare = GetDlgItemInt(TX_Square);
  1106. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  1107. long nSquare2 = GetDlgItemInt(TX_Square2);
  1108. if (nPos != 0)
  1109. {
  1110. // 二值化;
  1111. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1112. ImgThreshold(nPos, lMaxVal);
  1113. if (m_nRadio == 2)
  1114. {
  1115. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1116. }
  1117. else
  1118. {
  1119. // 刷新;
  1120. RefreshCanvas();
  1121. }
  1122. }
  1123. else
  1124. {
  1125. int nCurSel = m_cbThresholdType.GetCurSel();
  1126. if (nCurSel == 2 || nCurSel == 3)
  1127. {
  1128. // 二值化;
  1129. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1130. ImgThreshold(nPos, lMaxVal);
  1131. if (m_nRadio == 2)
  1132. {
  1133. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1134. }
  1135. else
  1136. {
  1137. // 刷新;
  1138. RefreshCanvas();
  1139. }
  1140. }
  1141. else
  1142. {
  1143. m_pRenderings = &m_ImgShow;
  1144. }
  1145. RefreshCanvas();
  1146. }
  1147. // TODO: 在此添加控件通知处理程序代码
  1148. }
  1149. void CThresholdToolsDlg::OnEnChangeTop()
  1150. {
  1151. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  1152. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  1153. // 函数并调用 CRichEditCtrl().SetEventMask(),
  1154. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  1155. OnEnChangeLeft();
  1156. // TODO: 在此添加控件通知处理程序代码
  1157. }
  1158. void CThresholdToolsDlg::OnEnChangeRight()
  1159. {
  1160. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  1161. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  1162. // 函数并调用 CRichEditCtrl().SetEventMask(),
  1163. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  1164. OnEnChangeLeft();
  1165. // TODO: 在此添加控件通知处理程序代码
  1166. }
  1167. void CThresholdToolsDlg::OnEnChangeBottom()
  1168. {
  1169. // TODO: 如果该控件是 RICHEDIT 控件,它将不
  1170. // 发送此通知,除非重写 CDialogEx::OnInitDialog()
  1171. // 函数并调用 CRichEditCtrl().SetEventMask(),
  1172. // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
  1173. OnEnChangeLeft();
  1174. // TODO: 在此添加控件通知处理程序代码
  1175. }
  1176. void CThresholdToolsDlg::OnBnClickedPreve()
  1177. {
  1178. // TODO: 在此添加控件通知处理程序代码
  1179. if (m_files.size() == 0)
  1180. return;
  1181. if (m_curIndex == 0 )
  1182. {
  1183. m_curIndex = m_files.size();
  1184. MessageBox(_T("已到第一张,将从最后一张继续"));
  1185. }
  1186. m_curIndex--;
  1187. OpenImg(m_files[m_curIndex].c_str());
  1188. }
  1189. void CThresholdToolsDlg::OnBnClickedNext()
  1190. {
  1191. if (m_files.size() == 0)
  1192. return;
  1193. if (m_curIndex == m_files.size()-1)
  1194. {
  1195. MessageBox(_T("已到最后一张,将从第一张继续"));
  1196. m_curIndex = -1;
  1197. }
  1198. m_curIndex++;
  1199. OpenImg(m_files[m_curIndex].c_str());
  1200. }
  1201. //打开图片;
  1202. void CThresholdToolsDlg::OpenImg(LPCTSTR lpFile, BOOL bResetROI /* = FALSE */)
  1203. {
  1204. int lastr = 0, lastc = 0;
  1205. if (m_Img.data != NULL)
  1206. {
  1207. lastr = m_Img.rows, lastc = m_Img.cols;
  1208. m_Img.release();
  1209. }
  1210. if (m_ImgThreshold.data)
  1211. {
  1212. m_ImgThreshold.release();
  1213. }
  1214. if ( m_ImgShow.data )
  1215. {
  1216. m_ImgShow.release();
  1217. }
  1218. if ( m_ImgROI.data )
  1219. {
  1220. m_ImgROI.release();
  1221. }
  1222. SetDlgItemText(IDC_EDIT1, lpFile);
  1223. m_Img = imread(lpFile, CV_LOAD_IMAGE_COLOR);
  1224. if (m_Img.data)
  1225. {
  1226. if (lastr != m_Img.rows && lastc != m_Img.cols)
  1227. bResetROI = TRUE;
  1228. if (bResetROI)
  1229. {
  1230. m_strLeft = _T("0");
  1231. m_strTop = _T("0");
  1232. m_strRight.Format(_T("%ld"), m_Img.cols);
  1233. m_strBottom.Format(_T("%ld"), m_Img.rows);
  1234. UpdateData(FALSE);
  1235. }
  1236. m_Img.copyTo(m_ImgShow);
  1237. }
  1238. int nPos = m_slider.GetPos();
  1239. int nCurSel = m_cbThresholdType.GetCurSel();
  1240. // 二值化;
  1241. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1242. ImgThreshold(nPos, lMaxVal);
  1243. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  1244. long nSquare = GetDlgItemInt(TX_Square);
  1245. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  1246. long nSquare2 = GetDlgItemInt(TX_Square2);
  1247. if (nCurSel == 2 || nCurSel == 3)
  1248. {
  1249. if (m_nRadio == 2)
  1250. {
  1251. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1252. }
  1253. else
  1254. {
  1255. // 刷新;
  1256. RefreshCanvas();
  1257. }
  1258. }
  1259. else
  1260. {
  1261. if (nPos != 0)
  1262. {
  1263. if (m_nRadio == 2)
  1264. {
  1265. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1266. }
  1267. else
  1268. {
  1269. // 刷新;
  1270. RefreshCanvas();
  1271. }
  1272. }
  1273. else
  1274. {
  1275. if (m_nRadio == 3)
  1276. {
  1277. OnBnClickedFindTemp();
  1278. }
  1279. else {
  1280. m_pRenderings = &m_Img;
  1281. RefreshCanvas();
  1282. }
  1283. }
  1284. }
  1285. //if (nPos != 0)
  1286. //{
  1287. // // 二值化;
  1288. // long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1289. // ImgThreshold(nPos, lMaxVal);
  1290. // long nPerimeter = GetDlgItemInt(TX_Perimeter);
  1291. // long nSquare = GetDlgItemInt(TX_Square);
  1292. // long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  1293. // long nSquare2 = GetDlgItemInt(TX_Square2);
  1294. // if (m_nRadio == 2)
  1295. // {
  1296. // DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1297. // }
  1298. // else
  1299. // {
  1300. // //if (m_ImgThreshold.data)
  1301. // // m_pRenderings = &m_ImgThreshold;
  1302. // // 刷新;
  1303. // RefreshCanvas();
  1304. // }
  1305. //}
  1306. //else
  1307. //{
  1308. // m_pRenderings = &m_ImgShow;
  1309. // RefreshCanvas();
  1310. //}
  1311. }
  1312. int CThresholdToolsDlg::GetFileIndex(LPCTSTR lpCurFile, STR_VEC & vtFiles)
  1313. {
  1314. int nIndex = -1;
  1315. int nCount = vtFiles.size();
  1316. for ( int i = 0; i < nCount; i++ )
  1317. {
  1318. if (!_tcsicmp(lpCurFile, vtFiles[i].c_str()) )
  1319. {
  1320. nIndex = i;
  1321. break;
  1322. }
  1323. }
  1324. return nIndex;
  1325. }
  1326. void CThresholdToolsDlg::OnBnClickedThreshold()
  1327. {
  1328. // TODO: 在此添加控件通知处理程序代码
  1329. UpdateData(TRUE);
  1330. long lVal = m_slider.GetPos();
  1331. long lMaxVal = GetDlgItemInt(IDC_EDIT2);
  1332. long nPerimeter = GetDlgItemInt(TX_Perimeter);
  1333. long nSquare = GetDlgItemInt(TX_Square);
  1334. long nPerimeter2 = GetDlgItemInt(TX_Perimeter2);
  1335. long nSquare2 = GetDlgItemInt(TX_Square2);
  1336. switch (m_nRadio)
  1337. {
  1338. case 0:
  1339. {
  1340. m_pRenderings = &m_Img;
  1341. // 刷新;
  1342. RefreshCanvas();
  1343. }
  1344. break;
  1345. case 1://二值图;
  1346. {
  1347. GetROI();
  1348. if (m_ImgThreshold.data)
  1349. {
  1350. cvtColor(m_ImgThreshold, m_ImgROI, COLOR_GRAY2BGR);
  1351. m_ImgThreshold.copyTo(m_ImgROI);
  1352. m_pRenderings = &m_ImgShow;
  1353. }
  1354. // 刷新;
  1355. RefreshCanvas();
  1356. }
  1357. break;
  1358. case 2:// 轮廓填充;
  1359. {
  1360. DrawContours(m_bPerimeter, nPerimeter, nPerimeter2, m_bSquare, nSquare, nSquare2);
  1361. }
  1362. break;
  1363. case 3:
  1364. {
  1365. OnBnClickedFindTemp();
  1366. }
  1367. break;
  1368. default:
  1369. break;
  1370. }
  1371. }
  1372. void CThresholdToolsDlg::OnBnClickedOpenTemp()//打开模板图片;
  1373. {
  1374. // TODO: 在此添加控件通知处理程序代码
  1375. CString strFindFile = _T("");
  1376. CString strFilters = _T("图片(*.jpg;*.jpeg;*.png;*.bmp;)||所有文件 (*.*)|*.*||");
  1377. CString strDeftExt = _T("default Files (*.png)");
  1378. CString strTitle = _T("请选择要取阀值的图片");
  1379. DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ENABLESIZING;
  1380. CFileDialog dlg(TRUE, strDeftExt, NULL, dwFlags, strFilters, NULL);
  1381. dlg.m_ofn.lpstrTitle = strTitle; // 显示的标题, 应该做成参数传入;
  1382. dlg.m_ofn.lpstrInitialDir = NULL; // 默认打开的文件夹, 应该做成参数传入;
  1383. // 显示文件对话框,获得文件名集合;
  1384. if (dlg.DoModal() == IDCANCEL)
  1385. return;
  1386. CString strFiles = dlg.GetPathName();
  1387. CString strPath = dlg.GetFolderPath();
  1388. if ( m_ImgTemp.data )
  1389. {
  1390. m_ImgTemp.release();
  1391. }
  1392. m_ImgTemp = imread(strFiles.GetString(), CV_LOAD_IMAGE_COLOR);
  1393. if ( m_ImgTemp.data)
  1394. {
  1395. DrawMat(m_ImgTemp, IDC_TEMP);
  1396. }
  1397. }
  1398. void CThresholdToolsDlg::OnBnClickedFindTemp()
  1399. {
  1400. // TODO: 在此添加控件通知处理程序代码
  1401. if (m_ImgTemp.data == NULL)
  1402. return;
  1403. if ( m_ImgTemp.cols > m_Img.cols || m_ImgTemp.rows > m_Img.rows)
  1404. return;
  1405. GetROI();
  1406. if (m_ImgROI.data == NULL)
  1407. return;
  1408. Mat ImgResult;
  1409. matchTemplate(m_ImgROI, m_ImgTemp, ImgResult, TM_CCOEFF_NORMED);
  1410. // 归一化到0~1
  1411. //normalize(ImgResult, ImgResult, 0, 1, NORM_MINMAX, -1);
  1412. //
  1413. double lv_nMinVal = 0.0;
  1414. double lv_nMaxVal = 0.0;
  1415. Point lv_nMinLoc = Point(0, 0);
  1416. Point lv_nMaxLoc = Point(0,0);
  1417. Point lv_MatchLoc = Point(0,0);
  1418. minMaxLoc(ImgResult, &lv_nMinVal, &lv_nMaxVal, &lv_nMinLoc, &lv_nMaxLoc);
  1419. // TM_CCOEFF_NORMED:匹配值越大越相似;
  1420. SetDlgItemText(MATCH_VAL, [&]()->CString{
  1421. CString str;
  1422. str.Format(_T("%0.13lf"), lv_nMaxVal);
  1423. return str;
  1424. }());
  1425. SetWindowText([&]()->CString {
  1426. CString str;
  1427. str.Format(_T("相似度=%0.13lf 坐标=[%d,%d,%d,%d]"), lv_nMaxVal, lv_nMaxLoc.x, lv_nMaxLoc.y, lv_nMaxLoc.x + m_ImgTemp.cols, lv_nMaxLoc.y + m_ImgTemp.rows);
  1428. return str;
  1429. }());
  1430. //m_Img.copyTo(m_ImgShow);
  1431. //m_ImgROI = m_ImgShow(Rect(lv_nMaxLoc.x-2, lv_nMaxLoc.y-2, m_ImgTemp.cols+4, m_ImgTemp.rows+4));
  1432. //m_ImgROI = m_ImgShow(Rect(lv_nMaxLoc.x, lv_nMaxLoc.y , m_ImgTemp.cols , m_ImgTemp.rows ));
  1433. //CV_AA
  1434. rectangle(m_ImgROI, Point(lv_nMaxLoc.x, lv_nMaxLoc.y), Point(lv_nMaxLoc.x+ m_ImgTemp.cols, lv_nMaxLoc.y+ m_ImgTemp.rows), Scalar(rand() % 255, rand() % 255, rand() % 255), 2, CV_AA, 0);
  1435. m_pRenderings = &m_ImgShow;
  1436. RefreshCanvas();
  1437. }
  1438. void CThresholdToolsDlg::DrawTempContours()
  1439. {
  1440. }