edgecontour.cpp
上传用户:renhuadsj
上传日期:2008-11-19
资源大小:1466k
文件大小:42k
源码类别:

图形图象

开发平台:

Visual C++

  1. // ************************************************************************
  2. //  文件名:edgecontour.cpp
  3. //
  4. //  图像边缘与轮廓运算API函数库:
  5. //
  6. //  RobertDIB() - robert边缘检测运算
  7. //  SobelDIB() - sobel边缘检测运算
  8. //  PrewittDIB() - prewitt边缘检测运算
  9. //  KirschDIB() - kirsch边缘检测运算
  10. //  GaussDIB() - gauss边缘检测运算
  11. //  HoughDIB() - 利用Hough变换检测平行直线
  12. //  ContourDIB() - 轮廓提取
  13. //  TraceDIB() - 轮廓跟踪
  14. //  FillDIB() - 种子填充算法1
  15. //  Fill2DIB() - 种子填充算法2
  16. //  添加水平和垂直边缘检测
  17. //  spDIB()         - 水平   
  18. //  czDIB()         - 垂直 
  19. //
  20. // ************************************************************************
  21. #include "stdafx.h"
  22. #include "edgecontour.h"
  23. #include "TemplateTrans.h"
  24. #include "DIBAPI.h"
  25. #include <math.h>
  26. #include <direct.h>
  27. /*************************************************************************
  28.  *
  29.  * 函数名称:
  30.  *   RobertDIB()
  31.  *
  32.  * 参数:
  33.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  34.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  35.  *   LONG  lHeight      - 源图像高度(象素数)
  36.  * 返回值:
  37.  *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
  38.  *
  39.  * 说明:
  40.  * 该函数用Robert边缘检测算子对图像进行边缘检测运算。
  41.  * 
  42.  * 要求目标图像为灰度图像。
  43.  ************************************************************************/
  44. BOOL WINAPI RobertDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  45. {
  46. // 指向源图像的指针
  47. LPSTR lpSrc;
  48. // 指向缓存图像的指针
  49. LPSTR lpDst;
  50. // 指向缓存DIB图像的指针
  51. LPSTR lpNewDIBBits;
  52. HLOCAL hNewDIBBits;
  53. //循环变量
  54. long i;
  55. long j;
  56. //像素值
  57. double result;
  58. unsigned char pixel[4];
  59. // 暂时分配内存,以保存新图像
  60. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  61. if (hNewDIBBits == NULL)
  62. {
  63. // 分配内存失败
  64. return FALSE;
  65. }
  66. // 锁定内存
  67. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  68. // 初始化新分配的内存,设定初始值为255
  69. lpDst = (char *)lpNewDIBBits;
  70. memset(lpDst, (BYTE)255, lWidth * lHeight);
  71. //使用水平方向的结构元素进行腐蚀
  72. for(j = lHeight-1; j > 0; j--)
  73. {
  74. for(i = 0;i <lWidth-1; i++)
  75. {
  76. //由于使用2×2的模板,为防止越界,所以不处理最下边和最右边的两列像素
  77. // 指向源图像第j行,第i个象素的指针
  78. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  79. // 指向目标图像第j行,第i个象素的指针
  80. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  81. //取得当前指针处2*2区域的像素值,注意要转换为unsigned char型
  82. pixel[0] = (unsigned char)*lpSrc;
  83. pixel[1] = (unsigned char)*(lpSrc + 1);
  84. pixel[2] = (unsigned char)*(lpSrc - lWidth);
  85. pixel[3] = (unsigned char)*(lpSrc - lWidth + 1);
  86. //计算目标图像中的当前点
  87.  result = sqrt(( pixel[0] - pixel[3] )*( pixel[0] - pixel[3] ) + 
  88.   ( pixel[1] - pixel[2] )*( pixel[1] - pixel[2] ));
  89. *lpDst = (unsigned char)result;
  90. }
  91. }
  92. // 复制腐蚀后的图像
  93. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  94. // 释放内存
  95. LocalUnlock(hNewDIBBits);
  96. LocalFree(hNewDIBBits);
  97. // 返回
  98. return TRUE;
  99. }
  100. /*************************************************************************
  101.  *
  102.  * 函数名称:
  103.  *   SobelDIB()
  104.  *
  105.  * 参数:
  106.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  107.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  108.  *   LONG  lHeight      - 源图像高度(象素数)
  109.  * 返回值:
  110.  *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
  111.  *
  112.  * 说明:
  113.  * 该函数用Sobel边缘检测算子对图像进行边缘检测运算。
  114.  * 
  115.  * 要求目标图像为灰度图像。
  116.  ************************************************************************/
  117. BOOL WINAPI SobelDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  118. {
  119. // 指向缓存图像的指针
  120. LPSTR lpDst1;
  121. LPSTR lpDst2;
  122. // 指向缓存DIB图像的指针
  123. LPSTR lpNewDIBBits1;
  124. HLOCAL hNewDIBBits1;
  125. LPSTR lpNewDIBBits2;
  126. HLOCAL hNewDIBBits2;
  127. //循环变量
  128. long i;
  129. long j;
  130. // 模板高度
  131. int iTempH;
  132. // 模板宽度
  133. int iTempW;
  134. // 模板系数
  135. FLOAT fTempC;
  136. // 模板中心元素X坐标
  137. int iTempMX;
  138. // 模板中心元素Y坐标
  139. int iTempMY;
  140. //模板数组
  141. FLOAT aTemplate[9];
  142. // 暂时分配内存,以保存新图像
  143. hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
  144. if (hNewDIBBits1 == NULL)
  145. {
  146. // 分配内存失败
  147. return FALSE;
  148. }
  149. // 锁定内存
  150. lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1);
  151. // 暂时分配内存,以保存新图像
  152. hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
  153. if (hNewDIBBits2 == NULL)
  154. {
  155. // 分配内存失败
  156. return FALSE;
  157. }
  158. // 锁定内存
  159. lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2);
  160. // 拷贝源图像到缓存图像中
  161. lpDst1 = (char *)lpNewDIBBits1;
  162. memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
  163. lpDst2 = (char *)lpNewDIBBits2;
  164. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  165. // 设置Sobel模板参数
  166. iTempW = 3;
  167. iTempH = 3;
  168. fTempC = 1.0;
  169. iTempMX = 1;
  170. iTempMY = 1;
  171. aTemplate[0] = -1.0;
  172. aTemplate[1] = -2.0;
  173. aTemplate[2] = -1.0;
  174. aTemplate[3] = 0.0;
  175. aTemplate[4] = 0.0;
  176. aTemplate[5] = 0.0;
  177. aTemplate[6] = 1.0;
  178. aTemplate[7] = 2.0;
  179. aTemplate[8] = 1.0;
  180. // 调用Template()函数
  181. if (!Template(lpNewDIBBits1, lWidth, lHeight, 
  182. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  183. {
  184. return FALSE;
  185. }
  186. // 设置Sobel模板参数
  187. aTemplate[0] = -1.0;
  188. aTemplate[1] = 0.0;
  189. aTemplate[2] = 1.0;
  190. aTemplate[3] = -2.0;
  191. aTemplate[4] = 0.0;
  192. aTemplate[5] = 2.0;
  193. aTemplate[6] = -1.0;
  194. aTemplate[7] = 0.0;
  195. aTemplate[8] = 1.0;
  196. // 调用Template()函数
  197. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  198. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  199. {
  200. return FALSE;
  201. }
  202. //求两幅缓存图像的最大值
  203. for(j = 0; j <lHeight; j++)
  204. {
  205. for(i = 0;i <lWidth-1; i++)
  206. {
  207. // 指向缓存图像1倒数第j行,第i个象素的指针
  208. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  209. // 指向缓存图像2倒数第j行,第i个象素的指针
  210. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  211. if(*lpDst2 > *lpDst1)
  212. *lpDst1 = *lpDst2;
  213. }
  214. }
  215. // 复制经过模板运算后的图像到源图像
  216. memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
  217. // 释放内存
  218. LocalUnlock(hNewDIBBits1);
  219. LocalFree(hNewDIBBits1);
  220. LocalUnlock(hNewDIBBits2);
  221. LocalFree(hNewDIBBits2);
  222. // 返回
  223. return TRUE;
  224. }
  225. /*************************************************************************
  226.  *
  227.  * 函数名称:
  228.  *   PrewittDIB()
  229.  *
  230.  * 参数:
  231.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  232.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  233.  *   LONG  lHeight      - 源图像高度(象素数)
  234.  * 返回值:
  235.  *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
  236.  *
  237.  * 说明:
  238.  * 该函数用Prewitt边缘检测算子对图像进行边缘检测运算。
  239.  * 
  240.  * 要求目标图像为灰度图像。
  241.  ************************************************************************/
  242. BOOL WINAPI PrewittDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  243. {
  244. // 指向缓存图像的指针
  245. LPSTR lpDst1;
  246. LPSTR lpDst2;
  247. // 指向缓存DIB图像的指针
  248. LPSTR lpNewDIBBits1;
  249. HLOCAL hNewDIBBits1;
  250. LPSTR lpNewDIBBits2;
  251. HLOCAL hNewDIBBits2;
  252. //循环变量
  253. long i;
  254. long j;
  255. // 模板高度
  256. int iTempH;
  257. // 模板宽度
  258. int iTempW;
  259. // 模板系数
  260. FLOAT fTempC;
  261. // 模板中心元素X坐标
  262. int iTempMX;
  263. // 模板中心元素Y坐标
  264. int iTempMY;
  265. //模板数组
  266. FLOAT aTemplate[9];
  267. // 暂时分配内存,以保存新图像
  268. hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
  269. if (hNewDIBBits1 == NULL)
  270. {
  271. // 分配内存失败
  272. return FALSE;
  273. }
  274. // 锁定内存
  275. lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1);
  276. // 暂时分配内存,以保存新图像
  277. hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
  278. if (hNewDIBBits2 == NULL)
  279. {
  280. // 分配内存失败
  281. return FALSE;
  282. }
  283. // 锁定内存
  284. lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2);
  285. // 拷贝源图像到缓存图像中
  286. lpDst1 = (char *)lpNewDIBBits1;
  287. memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
  288. lpDst2 = (char *)lpNewDIBBits2;
  289. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  290. // 设置Prewitt模板参数
  291. iTempW = 3;
  292. iTempH = 3;
  293. fTempC = 1.0;
  294. iTempMX = 1;
  295. iTempMY = 1;
  296. aTemplate[0] = -1.0;
  297. aTemplate[1] = -1.0;
  298. aTemplate[2] = -1.0;
  299. aTemplate[3] = 0.0;
  300. aTemplate[4] = 0.0;
  301. aTemplate[5] = 0.0;
  302. aTemplate[6] = 1.0;
  303. aTemplate[7] = 1.0;
  304. aTemplate[8] = 1.0;
  305. // 调用Template()函数
  306. if (!Template(lpNewDIBBits1, lWidth, lHeight, 
  307. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  308. {
  309. return FALSE;
  310. }
  311. // 设置Prewitt模板参数
  312. aTemplate[0] = 1.0;
  313. aTemplate[1] = 0.0;
  314. aTemplate[2] = -1.0;
  315. aTemplate[3] = 1.0;
  316. aTemplate[4] = 0.0;
  317. aTemplate[5] = -1.0;
  318. aTemplate[6] = 1.0;
  319. aTemplate[7] = 0.0;
  320. aTemplate[8] = -1.0;
  321. // 调用Template()函数
  322. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  323. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  324. {
  325. return FALSE;
  326. }
  327. //求两幅缓存图像的最大值
  328. for(j = 0; j <lHeight; j++)
  329. {
  330. for(i = 0;i <lWidth-1; i++)
  331. {
  332. // 指向缓存图像1倒数第j行,第i个象素的指针
  333. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  334. // 指向缓存图像2倒数第j行,第i个象素的指针
  335. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  336. if(*lpDst2 > *lpDst1)
  337. *lpDst1 = *lpDst2;
  338. }
  339. }
  340. // 复制经过模板运算后的图像到源图像
  341. memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
  342. // 释放内存
  343. LocalUnlock(hNewDIBBits1);
  344. LocalFree(hNewDIBBits1);
  345. LocalUnlock(hNewDIBBits2);
  346. LocalFree(hNewDIBBits2);
  347. // 返回
  348. return TRUE;
  349. }
  350. /*************************************************************************
  351.  *
  352.  * 函数名称:
  353.  *   KirschDIB()
  354.  *
  355.  * 参数:
  356.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  357.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  358.  *   LONG  lHeight      - 源图像高度(象素数)
  359.  * 返回值:
  360.  *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
  361.  *
  362.  * 说明:
  363.  * 该函数用kirsch边缘检测算子对图像进行边缘检测运算。
  364.  * 
  365.  * 要求目标图像为灰度图像。
  366.  ************************************************************************/
  367. BOOL WINAPI KirschDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  368. {
  369. // 指向缓存图像的指针
  370. LPSTR lpDst1;
  371. LPSTR lpDst2;
  372. // 指向缓存DIB图像的指针
  373. LPSTR lpNewDIBBits1;
  374. HLOCAL hNewDIBBits1;
  375. LPSTR lpNewDIBBits2;
  376. HLOCAL hNewDIBBits2;
  377. //循环变量
  378. long i;
  379. long j;
  380. // 模板高度
  381. int iTempH;
  382. // 模板宽度
  383. int iTempW;
  384. // 模板系数
  385. FLOAT fTempC;
  386. // 模板中心元素X坐标
  387. int iTempMX;
  388. // 模板中心元素Y坐标
  389. int iTempMY;
  390. //模板数组
  391. FLOAT aTemplate[9];
  392. // 暂时分配内存,以保存新图像
  393. hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
  394. if (hNewDIBBits1 == NULL)
  395. {
  396. // 分配内存失败
  397. return FALSE;
  398. }
  399. // 锁定内存
  400. lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1);
  401. // 暂时分配内存,以保存新图像
  402. hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
  403. if (hNewDIBBits2 == NULL)
  404. {
  405. // 分配内存失败
  406. return FALSE;
  407. }
  408. // 锁定内存
  409. lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2);
  410. // 拷贝源图像到缓存图像中
  411. lpDst1 = (char *)lpNewDIBBits1;
  412. memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
  413. lpDst2 = (char *)lpNewDIBBits2;
  414. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  415. // 设置Kirsch模板1参数
  416. iTempW = 3;
  417. iTempH = 3;
  418. fTempC = 1.0;
  419. iTempMX = 1;
  420. iTempMY = 1;
  421. aTemplate[0] = 5.0;
  422. aTemplate[1] = 5.0;
  423. aTemplate[2] = 5.0;
  424. aTemplate[3] = -3.0;
  425. aTemplate[4] = 0.0;
  426. aTemplate[5] = -3.0;
  427. aTemplate[6] = -3.0;
  428. aTemplate[7] = -3.0;
  429. aTemplate[8] = -3.0;
  430. // 调用Template()函数
  431. if (!Template(lpNewDIBBits1, lWidth, lHeight, 
  432. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  433. {
  434. return FALSE;
  435. }
  436. // 设置Kirsch模板2参数
  437. aTemplate[0] = -3.0;
  438. aTemplate[1] = 5.0;
  439. aTemplate[2] = 5.0;
  440. aTemplate[3] = -3.0;
  441. aTemplate[4] = 0.0;
  442. aTemplate[5] = 5.0;
  443. aTemplate[6] = -3.0;
  444. aTemplate[7] = -3.0;
  445. aTemplate[8] = -3.0;
  446. // 调用Template()函数
  447. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  448. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  449. {
  450. return FALSE;
  451. }
  452. //求两幅缓存图像的最大值
  453. for(j = 0; j <lHeight; j++)
  454. {
  455. for(i = 0;i <lWidth-1; i++)
  456. {
  457. // 指向缓存图像1倒数第j行,第i个象素的指针
  458. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  459. // 指向缓存图像2倒数第j行,第i个象素的指针
  460. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  461. if(*lpDst2 > *lpDst1)
  462. *lpDst1 = *lpDst2;
  463. }
  464. }
  465. // 拷贝源图像到缓存图像中
  466. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  467. // 设置Kirsch模板3参数
  468. aTemplate[0] = -3.0;
  469. aTemplate[1] = -3.0;
  470. aTemplate[2] = 5.0;
  471. aTemplate[3] = -3.0;
  472. aTemplate[4] = 0.0;
  473. aTemplate[5] = 5.0;
  474. aTemplate[6] = -3.0;
  475. aTemplate[7] = -3.0;
  476. aTemplate[8] = 5.0;
  477. // 调用Template()函数
  478. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  479. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  480. {
  481. return FALSE;
  482. }
  483. //求两幅缓存图像的最大值
  484. for(j = 0; j <lHeight; j++)
  485. {
  486. for(i = 0;i <lWidth-1; i++)
  487. {
  488. // 指向缓存图像1倒数第j行,第i个象素的指针
  489. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  490. // 指向缓存图像2倒数第j行,第i个象素的指针
  491. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  492. if(*lpDst2 > *lpDst1)
  493. *lpDst1 = *lpDst2;
  494. }
  495. }
  496. // 拷贝源图像到缓存图像中
  497. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  498. // 设置Kirsch模板4参数
  499. aTemplate[0] = -3.0;
  500. aTemplate[1] = -3.0;
  501. aTemplate[2] = -3.0;
  502. aTemplate[3] = -3.0;
  503. aTemplate[4] = 0.0;
  504. aTemplate[5] = 5.0;
  505. aTemplate[6] = -3.0;
  506. aTemplate[7] = 5.0;
  507. aTemplate[8] = 5.0;
  508. // 调用Template()函数
  509. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  510. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  511. {
  512. return FALSE;
  513. }
  514. //求两幅缓存图像的最大值
  515. for(j = 0; j <lHeight; j++)
  516. {
  517. for(i = 0;i <lWidth-1; i++)
  518. {
  519. // 指向缓存图像1倒数第j行,第i个象素的指针
  520. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  521. // 指向缓存图像2倒数第j行,第i个象素的指针
  522. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  523. if(*lpDst2 > *lpDst1)
  524. *lpDst1 = *lpDst2;
  525. }
  526. }
  527. // 拷贝源图像到缓存图像中
  528. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  529. // 设置Kirsch模板5参数
  530. aTemplate[0] = -3.0;
  531. aTemplate[1] = -3.0;
  532. aTemplate[2] = -3.0;
  533. aTemplate[3] = -3.0;
  534. aTemplate[4] = 0.0;
  535. aTemplate[5] = -3.0;
  536. aTemplate[6] = 5.0;
  537. aTemplate[7] = 5.0;
  538. aTemplate[8] = 5.0;
  539. // 调用Template()函数
  540. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  541. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  542. {
  543. return FALSE;
  544. }
  545. // 拷贝源图像到缓存图像中
  546. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  547. //求两幅缓存图像的最大值
  548. for(j = 0; j <lHeight; j++)
  549. {
  550. for(i = 0;i <lWidth-1; i++)
  551. {
  552. // 指向缓存图像1倒数第j行,第i个象素的指针
  553. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  554. // 指向缓存图像2倒数第j行,第i个象素的指针
  555. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  556. if(*lpDst2 > *lpDst1)
  557. *lpDst1 = *lpDst2;
  558. }
  559. }
  560. // 拷贝源图像到缓存图像中
  561. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  562. // 设置Kirsch模板6参数
  563. aTemplate[0] = -3.0;
  564. aTemplate[1] = -3.0;
  565. aTemplate[2] = -3.0;
  566. aTemplate[3] = 5.0;
  567. aTemplate[4] = 0.0;
  568. aTemplate[5] = -3.0;
  569. aTemplate[6] = 5.0;
  570. aTemplate[7] = 5.0;
  571. aTemplate[8] = -3.0;
  572. // 调用Template()函数
  573. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  574. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  575. {
  576. return FALSE;
  577. }
  578. //求两幅缓存图像的最大值
  579. for(j = 0; j <lHeight; j++)
  580. {
  581. for(i = 0;i <lWidth-1; i++)
  582. {
  583. // 指向缓存图像1倒数第j行,第i个象素的指针
  584. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  585. // 指向缓存图像2倒数第j行,第i个象素的指针
  586. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  587. if(*lpDst2 > *lpDst1)
  588. *lpDst1 = *lpDst2;
  589. }
  590. }
  591. // 拷贝源图像到缓存图像中
  592. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  593. // 设置Kirsch模板7参数
  594. aTemplate[0] = 5.0;
  595. aTemplate[1] = -3.0;
  596. aTemplate[2] = -3.0;
  597. aTemplate[3] = 5.0;
  598. aTemplate[4] = 0.0;
  599. aTemplate[5] = -3.0;
  600. aTemplate[6] = 5.0;
  601. aTemplate[7] = -3.0;
  602. aTemplate[8] = -3.0;
  603. // 调用Template()函数
  604. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  605. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  606. {
  607. return FALSE;
  608. }
  609. //求两幅缓存图像的最大值
  610. for(j = 0; j <lHeight; j++)
  611. {
  612. for(i = 0;i <lWidth-1; i++)
  613. {
  614. // 指向缓存图像1倒数第j行,第i个象素的指针
  615. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  616. // 指向缓存图像2倒数第j行,第i个象素的指针
  617. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  618. if(*lpDst2 > *lpDst1)
  619. *lpDst1 = *lpDst2;
  620. }
  621. }
  622. // 拷贝源图像到缓存图像中
  623. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  624. // 设置Kirsch模板8参数
  625. aTemplate[0] = 5.0;
  626. aTemplate[1] = 5.0;
  627. aTemplate[2] = -3.0;
  628. aTemplate[3] = 5.0;
  629. aTemplate[4] = 0.0;
  630. aTemplate[5] = -3.0;
  631. aTemplate[6] = -3.0;
  632. aTemplate[7] = -3.0;
  633. aTemplate[8] = -3.0;
  634. // 调用Template()函数
  635. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  636. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  637. {
  638. return FALSE;
  639. }
  640. //求两幅缓存图像的最大值
  641. for(j = 0; j <lHeight; j++)
  642. {
  643. for(i = 0;i <lWidth-1; i++)
  644. {
  645. // 指向缓存图像1倒数第j行,第i个象素的指针
  646. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  647. // 指向缓存图像2倒数第j行,第i个象素的指针
  648. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  649. if(*lpDst2 > *lpDst1)
  650. *lpDst1 = *lpDst2;
  651. }
  652. }
  653. // 复制经过模板运算后的图像到源图像
  654. memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
  655. // 释放内存
  656. LocalUnlock(hNewDIBBits1);
  657. LocalFree(hNewDIBBits1);
  658. LocalUnlock(hNewDIBBits2);
  659. LocalFree(hNewDIBBits2);
  660. // 返回
  661. return TRUE;
  662. }
  663. /*************************************************************************
  664.  *
  665.  * 函数名称:
  666.  *  GaussDIB()
  667.  *
  668.  * 参数:
  669.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  670.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  671.  *   LONG  lHeight      - 源图像高度(象素数)
  672.  * 返回值:
  673.  *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
  674.  *
  675.  * 说明:
  676.  * 该函数用高斯拉普拉斯边缘检测算子对图像进行边缘检测运算。
  677.  * 
  678.  * 要求目标图像为灰度图像。
  679.  ************************************************************************/
  680. BOOL WINAPI GaussDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  681. {
  682. // 指向缓存图像的指针
  683. LPSTR lpDst1;
  684. LPSTR lpDst2;
  685. // 指向缓存DIB图像的指针
  686. LPSTR lpNewDIBBits1;
  687. HLOCAL hNewDIBBits1;
  688. LPSTR lpNewDIBBits2;
  689. HLOCAL hNewDIBBits2;
  690. // 模板高度
  691. int iTempH;
  692. // 模板宽度
  693. int iTempW;
  694. // 模板系数
  695. FLOAT fTempC;
  696. // 模板中心元素X坐标
  697. int iTempMX;
  698. // 模板中心元素Y坐标
  699. int iTempMY;
  700. //模板数组
  701. FLOAT aTemplate[25];
  702. // 暂时分配内存,以保存新图像
  703. hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
  704. if (hNewDIBBits1 == NULL)
  705. {
  706. // 分配内存失败
  707. return FALSE;
  708. }
  709. // 锁定内存
  710. lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1);
  711. // 暂时分配内存,以保存新图像
  712. hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
  713. if (hNewDIBBits2 == NULL)
  714. {
  715. // 分配内存失败
  716. return FALSE;
  717. }
  718. // 锁定内存
  719. lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2);
  720. // 拷贝源图像到缓存图像中
  721. lpDst1 = (char *)lpNewDIBBits1;
  722. memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
  723. lpDst2 = (char *)lpNewDIBBits2;
  724. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  725. // 设置Gauss模板参数
  726. iTempW = 5;
  727. iTempH = 5;
  728. fTempC = 1.0;
  729. iTempMX = 3;
  730. iTempMY = 3;
  731. aTemplate[0] = -2.0;
  732. aTemplate[1] = -4.0;
  733. aTemplate[2] = -4.0;
  734. aTemplate[3] = -4.0;
  735. aTemplate[4] = -2.0;
  736. aTemplate[5] = -4.0;
  737. aTemplate[6] = 0.0;
  738. aTemplate[7] = 8.0;
  739. aTemplate[8] = 0.0;
  740. aTemplate[9] = -4.0;
  741. aTemplate[10] = -4.0;
  742. aTemplate[11] = 8.0;
  743. aTemplate[12] = 24.0;
  744. aTemplate[13] = 8.0;
  745. aTemplate[14] = -4.0;
  746. aTemplate[15] = -4.0;
  747. aTemplate[16] = 0.0;
  748. aTemplate[17] = 8.0;
  749. aTemplate[18] = 0.0;
  750. aTemplate[19] = -4.0;
  751. aTemplate[20] = -2.0;
  752. aTemplate[21] = -4.0;
  753. aTemplate[22] = -4.0;
  754. aTemplate[23] = -4.0;
  755. aTemplate[24] = -2.0;
  756. // 调用Template()函数
  757. if (!Template(lpNewDIBBits1, lWidth, lHeight, 
  758. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  759. {
  760. return FALSE;
  761. }
  762. // 复制经过模板运算后的图像到源图像
  763. memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
  764. // 释放内存
  765. LocalUnlock(hNewDIBBits1);
  766. LocalFree(hNewDIBBits1);
  767. LocalUnlock(hNewDIBBits2);
  768. LocalFree(hNewDIBBits2);
  769. // 返回
  770. return TRUE;
  771. }
  772. /*************************************************************************
  773.  *
  774.  * 函数名称:
  775.  *   HoughDIB()
  776.  *
  777.  * 参数:
  778.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  779.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  780.  *   LONG  lHeight      - 源图像高度(象素数)
  781.  * 返回值:
  782.  *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
  783.  *
  784.  * 说明:
  785.  * 该函数用于对检测图像中的平行直线。如果图像中有两条平行的直线,则将这两条平行直线
  786.  * 提取出来。
  787.  * 
  788.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  789.  ************************************************************************/
  790. BOOL WINAPI HoughDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  791. {
  792. // 指向源图像的指针
  793. LPSTR lpSrc;
  794. // 指向缓存图像的指针
  795. LPSTR lpDst;
  796. // 指向变换域的指针
  797. LPSTR   lpTrans;
  798. // 图像每行的字节数
  799. LONG lLineBytes;
  800. // 指向缓存DIB图像的指针
  801. LPSTR lpNewDIBBits;
  802. HLOCAL hNewDIBBits;
  803. //指向变换域的指针
  804. LPSTR lpTransArea;
  805. HLOCAL hTransArea;
  806. //变换域的尺寸
  807. int iMaxDist;
  808. int iMaxAngleNumber;
  809. //变换域的坐标
  810. int iDist;
  811. int iAngleNumber;
  812. //循环变量
  813. long i;
  814. long j;
  815. //像素值
  816. unsigned char pixel;
  817. //存储变换域中的两个最大值
  818. MaxValue MaxValue1;
  819. MaxValue MaxValue2;
  820. // 暂时分配内存,以保存新图像
  821. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  822. if (hNewDIBBits == NULL)
  823. {
  824. // 分配内存失败
  825. return FALSE;
  826. }
  827. // 锁定内存
  828. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  829. // 初始化新分配的内存,设定初始值为255
  830. lpDst = (char *)lpNewDIBBits;
  831. memset(lpDst, (BYTE)255, lWidth * lHeight);
  832. //计算变换域的尺寸
  833. //最大距离
  834. iMaxDist = (int) sqrt(lWidth*lWidth + lHeight*lHeight);
  835. //角度从0-180,每格2度
  836. iMaxAngleNumber = 90;
  837. //为变换域分配内存
  838. hTransArea = LocalAlloc(LHND, lWidth * lHeight * sizeof(int));
  839. if (hNewDIBBits == NULL)
  840. {
  841. // 分配内存失败
  842. return FALSE;
  843. }
  844. // 锁定内存
  845. lpTransArea = (char * )LocalLock(hTransArea);
  846. // 初始化新分配的内存,设定初始值为0
  847. lpTrans = (char *)lpTransArea;
  848. memset(lpTrans, 0, lWidth * lHeight * sizeof(int));
  849. // 计算图像每行的字节数
  850. lLineBytes = WIDTHBYTES(lWidth * 8);
  851. for(j = 0; j <lHeight; j++)
  852. {
  853. for(i = 0;i <lWidth; i++)
  854. {
  855. // 指向源图像倒数第j行,第i个象素的指针
  856. lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
  857. //取得当前指针处的像素值,注意要转换为unsigned char型
  858. pixel = (unsigned char)*lpSrc;
  859. //目标图像中含有0和255外的其它灰度值
  860. if(pixel != 255 && *lpSrc != 0)
  861. return FALSE;
  862. //如果是黑点,则在变换域的对应各点上加1
  863. if(pixel == 0)
  864. {
  865. //注意步长是2度
  866. for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++)
  867. {
  868. iDist = (int) fabs(i*cos(iAngleNumber*2*pi/180.0) + 
  869. j*sin(iAngleNumber*2*pi/180.0));
  870. //变换域的对应点上加1
  871. *(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) = 
  872. *(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) +1;
  873. }
  874. }
  875. }
  876. }
  877. //找到变换域中的两个最大值点
  878. MaxValue1.Value=0;
  879. MaxValue2.Value=0;
  880. //找到第一个最大值点
  881. for (iDist=0; iDist<iMaxDist;iDist++)
  882. {
  883. for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++)
  884. {
  885. if((int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)>MaxValue1.Value)
  886. {
  887. MaxValue1.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber);
  888. MaxValue1.Dist = iDist;
  889. MaxValue1.AngleNumber = iAngleNumber;
  890. }
  891. }
  892. }
  893. //将第一个最大值点附近清零
  894. for (iDist = -9;iDist < 10;iDist++)
  895. {
  896. for(iAngleNumber=-1; iAngleNumber<2; iAngleNumber++)
  897. {
  898. if(iDist+MaxValue1.Dist>=0 && iDist+MaxValue1.Dist<iMaxDist 
  899. && iAngleNumber+MaxValue1.AngleNumber>=0 && iAngleNumber+MaxValue1.AngleNumber<=iMaxAngleNumber)
  900. {
  901. *(lpTransArea+(iDist+MaxValue1.Dist)*iMaxAngleNumber+
  902. (iAngleNumber+MaxValue1.AngleNumber))=0;
  903. }
  904. }
  905. }
  906. //找到第二个最大值点
  907. for (iDist=0; iDist<iMaxDist;iDist++)
  908. {
  909. for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; iAngleNumber++)
  910. {
  911. if((int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)>MaxValue2.Value)
  912. {
  913. MaxValue2.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber);
  914. MaxValue2.Dist = iDist;
  915. MaxValue2.AngleNumber = iAngleNumber;
  916. }
  917. }
  918. }
  919. //判断两直线是否平行
  920. if(abs(MaxValue1.AngleNumber-MaxValue2.AngleNumber)<=2)
  921. {
  922. //两直线平行,在缓存图像中重绘这两条直线
  923. for(j = 0; j <lHeight; j++)
  924. {
  925. for(i = 0;i <lWidth; i++)
  926. {
  927. // 指向缓存图像倒数第j行,第i个象素的指针
  928. lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
  929. //如果该点在某一条平行直线上,则在缓存图像上将该点赋为黑
  930. //在第一条直线上
  931. iDist = (int) fabs(i*cos(MaxValue1.AngleNumber*2*pi/180.0) + 
  932. j*sin(MaxValue1.AngleNumber*2*pi/180.0));
  933. if (iDist == MaxValue1.Dist)
  934. *lpDst = (unsigned char)0;
  935. //在第二条直线上
  936. iDist = (int) fabs(i*cos(MaxValue2.AngleNumber*2*pi/180.0) + 
  937. j*sin(MaxValue2.AngleNumber*2*pi/180.0));
  938. if (iDist == MaxValue2.Dist)
  939. *lpDst = (unsigned char)0;
  940. }
  941. }
  942. }
  943. // 复制腐蚀后的图像
  944. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  945. // 释放内存
  946. LocalUnlock(hNewDIBBits);
  947. LocalFree(hNewDIBBits);
  948. // 释放内存
  949. LocalUnlock(hTransArea);
  950. LocalFree(hTransArea);
  951. // 返回
  952. return TRUE;
  953. }
  954. /*************************************************************************
  955.  *
  956.  * 函数名称:
  957.  *   Fill2DIB()
  958.  *
  959.  * 参数:
  960.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  961.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  962.  *   LONG  lHeight      - 源图像高度(象素数)
  963.  * 返回值:
  964.  *   BOOL               - 种子填充成功返回TRUE,否则返回FALSE。
  965.  *
  966.  * 说明:
  967.  * 该函数用于对图像进行种子填充运算。
  968.  * 
  969.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  970.  ************************************************************************/
  971. BOOL WINAPI Fill2DIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  972. {
  973. // 指向源图像的指针
  974. LPSTR lpSrc;
  975. //循环变量
  976. long i;
  977. //像素值
  978. unsigned char pixel;
  979. //左右边界像素位置
  980. int xl,xr;
  981. //是否已填充至边界
  982. BOOL bFilll,bFillr;
  983. //种子堆栈及指针
  984. Seed Seeds[10];
  985. int StackPoint;
  986. //当前像素位置
  987. int iCurrentPixelx,iCurrentPixely;
  988. int iBufferPixelx,iBufferPixely;
  989. //初始化种子
  990. Seeds[1].Height = lHeight / 2;
  991. Seeds[1].Width = lWidth / 2;
  992. StackPoint = 1;
  993. while( StackPoint != 0)
  994. {
  995. //取出种子
  996. iCurrentPixelx = Seeds[StackPoint].Width;
  997. iCurrentPixely = Seeds[StackPoint].Height;
  998. StackPoint--;
  999. // if(Seed2.Height== 75)
  1000. // {
  1001. // return true;
  1002. // i++;
  1003. // }
  1004. bFilll = true;
  1005. bFillr = true;
  1006. //填充种子所在的行
  1007. //保存种子像素的位置
  1008. iBufferPixelx = iCurrentPixelx;
  1009. iBufferPixely = iCurrentPixely;
  1010. //先向左填充
  1011. while(bFilll)
  1012. {
  1013. lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
  1014. //取得当前指针处的像素值,注意要转换为unsigned char型
  1015. pixel = (unsigned char)*lpSrc;
  1016. //目标图像中含有0和255外的其它灰度值
  1017. if(pixel != 255 && pixel != 0)
  1018. return FALSE;
  1019. //遇到边界
  1020. if(pixel == 0)
  1021. {
  1022. bFilll = false;
  1023. xl=iCurrentPixelx+1;
  1024. }
  1025. else
  1026. {
  1027. *lpSrc = (unsigned char)0;
  1028. iCurrentPixelx--;
  1029. //防止越界
  1030. if(iCurrentPixelx<0)
  1031. {
  1032. bFilll = false;
  1033. iCurrentPixelx = 0;
  1034. xl = 0; 
  1035. }
  1036. }
  1037. }
  1038. //再向右填充
  1039. //取回种子像素的位置
  1040. iCurrentPixelx = iBufferPixelx+1;
  1041. if(iCurrentPixelx>lWidth)
  1042. {
  1043. bFillr = false;
  1044. iCurrentPixelx = lWidth;
  1045. xr = lWidth; 
  1046. }
  1047. iCurrentPixely = iBufferPixely;
  1048. while(bFillr)
  1049. {
  1050. lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
  1051. //取得当前指针处的像素值,注意要转换为unsigned char型
  1052. pixel = (unsigned char)*lpSrc;
  1053. //目标图像中含有0和255外的其它灰度值
  1054. if(pixel != 255 && pixel != 0)
  1055. return FALSE;
  1056. //遇到边界
  1057. if(pixel == 0)
  1058. {
  1059. bFillr = false;
  1060. xr=iCurrentPixelx-1;
  1061. }
  1062. else
  1063. {
  1064. *lpSrc = (unsigned char)0;
  1065. iCurrentPixelx++;
  1066. //防止越界
  1067. if(iCurrentPixelx>lWidth)
  1068. {
  1069. bFillr = false;
  1070. iCurrentPixelx = lWidth;
  1071. xr = lWidth; 
  1072. }
  1073. }
  1074. }
  1075. //上、下两条扫描线是否全为边界象素或已填充过
  1076. //先看上面的扫描线
  1077. iCurrentPixely--;
  1078. if(iCurrentPixely < 0)
  1079. {
  1080. iCurrentPixely = 0;
  1081. }
  1082. for (i = xr; i>= xl;i--)
  1083. {
  1084. lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i;
  1085. //取得当前指针处的像素值,注意要转换为unsigned char型
  1086. pixel = (unsigned char)*lpSrc;
  1087. //有未填充的像素,将新的种子压入堆栈
  1088. if (pixel == 255)
  1089. {
  1090. StackPoint++;
  1091. Seeds[StackPoint].Height = iCurrentPixely;
  1092. Seeds[StackPoint].Width = i;
  1093. break;
  1094. }
  1095. }
  1096. //再看下面的扫描线
  1097. iCurrentPixely+=2;
  1098. if(iCurrentPixely > lHeight)
  1099. {
  1100. iCurrentPixely = lHeight;
  1101. }
  1102. for (i = xr; i>= xl;i--)
  1103. {
  1104. lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + i;
  1105. //取得当前指针处的像素值,注意要转换为unsigned char型
  1106. pixel = (unsigned char)*lpSrc;
  1107. //有未填充的像素,将新的种子压入堆栈
  1108. if (pixel == 255)
  1109. {
  1110. StackPoint++;
  1111. Seeds[StackPoint].Height = iCurrentPixely;
  1112. Seeds[StackPoint].Width = i;
  1113. break;
  1114. }
  1115. }
  1116. }
  1117. // 返回
  1118. return TRUE;
  1119. }
  1120. /*************************************************************************
  1121.  *
  1122.  * 函数名称:
  1123.  *   FillDIB()
  1124.  *
  1125.  * 参数:
  1126.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  1127.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  1128.  *   LONG  lHeight      - 源图像高度(象素数)
  1129.  * 返回值:
  1130.  *   BOOL               - 种子填充成功返回TRUE,否则返回FALSE。
  1131.  *
  1132.  * 说明:
  1133.  * 该函数用于对图像进行种子填充运算。
  1134.  * 
  1135.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  1136.  ************************************************************************/
  1137. BOOL WINAPI FillDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  1138. {
  1139. // 指向源图像的指针
  1140. LPSTR lpSrc;
  1141. //像素值
  1142. unsigned char pixel;
  1143. //种子堆栈及指针
  1144. Seed *Seeds;
  1145. int StackPoint;
  1146. //当前像素位置
  1147. int iCurrentPixelx,iCurrentPixely;
  1148. //初始化种子
  1149. Seeds = new Seed[lWidth*lHeight];
  1150. Seeds[1].Height = lHeight / 2;
  1151. Seeds[1].Width = lWidth / 2;
  1152. StackPoint = 1;
  1153. while( StackPoint != 0)
  1154. {
  1155. //取出种子
  1156. iCurrentPixelx = Seeds[StackPoint].Width;
  1157. iCurrentPixely = Seeds[StackPoint].Height;
  1158. StackPoint--;
  1159. lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx;
  1160. //取得当前指针处的像素值,注意要转换为unsigned char型
  1161. pixel = (unsigned char)*lpSrc;
  1162. //目标图像中含有0和255外的其它灰度值
  1163. if(pixel != 255 && pixel != 0)
  1164. return FALSE;
  1165. //将当前点涂黑
  1166. *lpSrc = (unsigned char)0;
  1167. //判断左面的点,如果为白,则压入堆栈
  1168. //注意防止越界
  1169. if(iCurrentPixelx > 0)
  1170. {
  1171. lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx - 1;
  1172. //取得当前指针处的像素值,注意要转换为unsigned char型
  1173. pixel = (unsigned char)*lpSrc;
  1174. if (pixel == 255)
  1175. {
  1176. StackPoint++;
  1177. Seeds[StackPoint].Height = iCurrentPixely;
  1178. Seeds[StackPoint].Width = iCurrentPixelx - 1;
  1179. }
  1180. //目标图像中含有0和255外的其它灰度值
  1181. if(pixel != 255 && pixel != 0)
  1182. return FALSE;
  1183. }
  1184. //判断上面的点,如果为白,则压入堆栈
  1185. //注意防止越界
  1186. if(iCurrentPixely < lHeight - 1)
  1187. {
  1188. lpSrc = (char *)lpDIBBits + lWidth * (iCurrentPixely + 1) + iCurrentPixelx;
  1189. //取得当前指针处的像素值,注意要转换为unsigned char型
  1190. pixel = (unsigned char)*lpSrc;
  1191. if (pixel == 255)
  1192. {
  1193. StackPoint++;
  1194. Seeds[StackPoint].Height = iCurrentPixely + 1;
  1195. Seeds[StackPoint].Width = iCurrentPixelx;
  1196. }
  1197. //目标图像中含有0和255外的其它灰度值
  1198. if(pixel != 255 && pixel != 0)
  1199. return FALSE;
  1200. }
  1201. //判断右面的点,如果为白,则压入堆栈
  1202. //注意防止越界
  1203. if(iCurrentPixelx < lWidth - 1)
  1204. {
  1205. lpSrc = (char *)lpDIBBits + lWidth * iCurrentPixely + iCurrentPixelx + 1;
  1206. //取得当前指针处的像素值,注意要转换为unsigned char型
  1207. pixel = (unsigned char)*lpSrc;
  1208. if (pixel == 255)
  1209. {
  1210. StackPoint++;
  1211. Seeds[StackPoint].Height = iCurrentPixely;
  1212. Seeds[StackPoint].Width = iCurrentPixelx + 1;
  1213. }
  1214. //目标图像中含有0和255外的其它灰度值
  1215. if(pixel != 255 && pixel != 0)
  1216. return FALSE;
  1217. }
  1218. //判断下面的点,如果为白,则压入堆栈
  1219. //注意防止越界
  1220. if(iCurrentPixely > 0)
  1221. {
  1222. lpSrc = (char *)lpDIBBits + lWidth * (iCurrentPixely - 1) + iCurrentPixelx;
  1223. //取得当前指针处的像素值,注意要转换为unsigned char型
  1224. pixel = (unsigned char)*lpSrc;
  1225. if (pixel == 255)
  1226. {
  1227. StackPoint++;
  1228. Seeds[StackPoint].Height = iCurrentPixely - 1;
  1229. Seeds[StackPoint].Width = iCurrentPixelx;
  1230. }
  1231. //目标图像中含有0和255外的其它灰度值
  1232. if(pixel != 255 && pixel != 0)
  1233. return FALSE;
  1234. }
  1235. }
  1236. //释放堆栈
  1237. delete Seeds;
  1238. // 返回
  1239. return TRUE;
  1240. }
  1241. /*************************************************************************
  1242.  *
  1243.  * 函数名称:
  1244.  *   ContourDIB()
  1245.  *
  1246.  * 参数:
  1247.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  1248.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  1249.  *   LONG  lHeight      - 源图像高度(象素数)
  1250.  * 返回值:
  1251.  *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
  1252.  *
  1253.  * 说明:
  1254.  * 该函数用于对图像进行轮廓提取运算。
  1255.  * 
  1256.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  1257.  ************************************************************************/
  1258. BOOL WINAPI ContourDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  1259. {
  1260. // 指向源图像的指针
  1261. LPSTR lpSrc;
  1262. // 指向缓存图像的指针
  1263. LPSTR lpDst;
  1264. // 指向缓存DIB图像的指针
  1265. LPSTR lpNewDIBBits;
  1266. HLOCAL hNewDIBBits;
  1267. //循环变量
  1268. long i;
  1269. long j;
  1270. unsigned char n,e,s,w,ne,se,nw,sw;
  1271. //像素值
  1272. unsigned char pixel;
  1273. // 暂时分配内存,以保存新图像
  1274. hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
  1275. if (hNewDIBBits == NULL)
  1276. {
  1277. // 分配内存失败
  1278. return FALSE;
  1279. }
  1280. // 锁定内存
  1281. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  1282. // 初始化新分配的内存,设定初始值为255
  1283. lpDst = (char *)lpNewDIBBits;
  1284. memset(lpDst, (BYTE)255, lWidth * lHeight);
  1285. for(j = 1; j <lHeight-1; j++)
  1286. {
  1287. for(i = 1;i <lWidth-1; i++)
  1288. {
  1289. // 指向源图像倒数第j行,第i个象素的指针
  1290. lpSrc = (char *)lpDIBBits + lWidth * j + i;
  1291. // 指向目标图像倒数第j行,第i个象素的指针
  1292. lpDst = (char *)lpNewDIBBits + lWidth * j + i;
  1293. //取得当前指针处的像素值,注意要转换为unsigned char型
  1294. pixel = (unsigned char)*lpSrc;
  1295. //目标图像中含有0和255外的其它灰度值
  1296. // if(pixel != 255 && pixel != 0)
  1297. // return FALSE;
  1298. if(pixel == 0)
  1299. {
  1300. *lpDst = (unsigned char)0;
  1301. nw = (unsigned char)*(lpSrc + lWidth -1);
  1302. n  = (unsigned char)*(lpSrc + lWidth );
  1303. ne = (unsigned char)*(lpSrc + lWidth +1);
  1304. w = (unsigned char)*(lpSrc -1);
  1305. e = (unsigned char)*(lpSrc +1);
  1306. sw = (unsigned char)*(lpSrc - lWidth -1);
  1307. s  = (unsigned char)*(lpSrc - lWidth );
  1308. se = (unsigned char)*(lpSrc - lWidth +1);
  1309. //如果相邻的八个点都是黑点
  1310. if(nw+n+ne+w+e+sw+s+se==0)
  1311. {
  1312. *lpDst = (unsigned char)255;
  1313. }
  1314. }
  1315. }
  1316. }
  1317. // 复制腐蚀后的图像
  1318. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  1319. // 释放内存
  1320. LocalUnlock(hNewDIBBits);
  1321. LocalFree(hNewDIBBits);
  1322. // 返回
  1323. return TRUE;
  1324. }
  1325. /*************************************************************************
  1326.  *
  1327.  * 函数名称:
  1328.  *   TraceDIB()
  1329.  *
  1330.  * 参数:
  1331.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  1332.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  1333.  *   LONG  lHeight      - 源图像高度(象素数)
  1334.  * 返回值:
  1335.  *   BOOL               - 运算成功返回TRUE,否则返回FALSE。
  1336.  *
  1337.  * 说明:
  1338.  * 该函数用于对图像进行轮廓跟踪运算。
  1339.  * 
  1340.  * 要求目标图像为只有0和255两个灰度值的灰度图像。
  1341.  ************************************************************************/
  1342. BOOL WINAPI TraceDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  1343. {
  1344. // 指向源图像的指针
  1345. LPSTR lpSrc;
  1346. // 指向缓存图像的指针
  1347. LPSTR lpDst;
  1348. // 指向缓存DIB图像的指针
  1349. LPSTR lpNewDIBBits;
  1350. HLOCAL hNewDIBBits;
  1351. // 图像每行的字节数
  1352. LONG lLineBytes;
  1353. //循环变量
  1354. long i;
  1355. long j;
  1356. //像素值
  1357. unsigned char pixel;
  1358. //是否找到起始点及回到起始点
  1359. bool bFindStartPoint;
  1360. //是否扫描到一个边界点
  1361. bool bFindPoint;
  1362. //起始边界点与当前边界点
  1363. Point StartPoint,CurrentPoint;
  1364. //八个方向和起始扫描方向
  1365. int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
  1366. int BeginDirect;
  1367. // 计算图像每行的字节数
  1368. lLineBytes = WIDTHBYTES(lWidth * 8);
  1369. // 暂时分配内存,以保存新图像
  1370. hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
  1371. if (hNewDIBBits == NULL)
  1372. {
  1373. // 分配内存失败
  1374. return FALSE;
  1375. }
  1376. // 锁定内存
  1377. lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
  1378. // 初始化新分配的内存,设定初始值为255
  1379. lpDst = (char *)lpNewDIBBits;
  1380. memset(lpDst, (BYTE)255, lLineBytes * lHeight);
  1381. //先找到最左上方的边界点
  1382. bFindStartPoint = false;
  1383. for (j = 0;j < lHeight && !bFindStartPoint;j++)
  1384. {
  1385. for(i = 0;i < lWidth && !bFindStartPoint;i++)
  1386. {
  1387. // 指向源图像倒数第j行,第i个象素的指针
  1388. lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
  1389. //取得当前指针处的像素值,注意要转换为unsigned char型
  1390. pixel = (unsigned char)*lpSrc;
  1391. if(pixel == 0)
  1392. {
  1393. bFindStartPoint = true;
  1394. StartPoint.Height = j;
  1395. StartPoint.Width = i;
  1396. // 指向目标图像倒数第j行,第i个象素的指针
  1397. lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
  1398. *lpDst = (unsigned char)0;
  1399. }
  1400. }
  1401. }
  1402. //由于起始点是在左下方,故起始扫描沿左上方向
  1403. BeginDirect = 0;
  1404. //跟踪边界
  1405. bFindStartPoint = false;
  1406. //从初始点开始扫描
  1407. CurrentPoint.Height = StartPoint.Height;
  1408. CurrentPoint.Width = StartPoint.Width;
  1409. while(!bFindStartPoint)
  1410. {
  1411. bFindPoint = false;
  1412. while(!bFindPoint)
  1413. {
  1414. //沿扫描方向查看一个像素
  1415. lpSrc = (char *)lpDIBBits + lLineBytes * ( CurrentPoint.Height + Direction[BeginDirect][1])
  1416. + (CurrentPoint.Width + Direction[BeginDirect][0]);
  1417. pixel = (unsigned char)*lpSrc;
  1418. if(pixel == 0)
  1419. {
  1420. bFindPoint = true;
  1421. CurrentPoint.Height = CurrentPoint.Height + Direction[BeginDirect][1];
  1422. CurrentPoint.Width = CurrentPoint.Width + Direction[BeginDirect][0];
  1423. if(CurrentPoint.Height == StartPoint.Height && CurrentPoint.Width == StartPoint.Width)
  1424. {
  1425. bFindStartPoint = true;
  1426. }
  1427. lpDst = (char *)lpNewDIBBits + lLineBytes * CurrentPoint.Height + CurrentPoint.Width;
  1428. *lpDst = (unsigned char)0;
  1429. //扫描的方向逆时针旋转两格
  1430. BeginDirect--;
  1431. if(BeginDirect == -1)
  1432. BeginDirect = 7;
  1433. BeginDirect--;
  1434. if(BeginDirect == -1)
  1435. BeginDirect = 7;
  1436. }
  1437. else
  1438. {
  1439. //扫描方向顺时针旋转一格
  1440. BeginDirect++;
  1441. if(BeginDirect == 8)
  1442. BeginDirect = 0;
  1443. }
  1444. }
  1445. }
  1446. // 复制腐蚀后的图像
  1447. memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
  1448. // 释放内存
  1449. LocalUnlock(hNewDIBBits);
  1450. LocalFree(hNewDIBBits);
  1451. // 返回
  1452. return TRUE;
  1453. }
  1454. /*************************************************************************
  1455.  *
  1456.  * 函数名称:
  1457.  *   MyDIB()
  1458.  *
  1459.  * 参数:
  1460.  *   LPSTR lpDIBBits    - 指向源DIB图像指针
  1461.  *   LONG  lWidth       - 源图像宽度(象素数,必须是4的倍数)
  1462.  *   LONG  lHeight      - 源图像高度(象素数)
  1463.  * 返回值:
  1464.  *   BOOL               - 边缘检测成功返回TRUE,否则返回FALSE。
  1465.  *
  1466.  * 说明:
  1467.  * 该函数用水平边缘检测算子对图像进行边缘检测运算。
  1468.  * 
  1469.  * 要求目标图像为灰度图像。
  1470.  ************************************************************************/
  1471. BOOL WINAPI MyDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
  1472. {
  1473. // 指向缓存图像的指针
  1474. LPSTR lpDst1;
  1475. LPSTR lpDst2;
  1476. // 指向缓存DIB图像的指针
  1477. LPSTR lpNewDIBBits1;
  1478. HLOCAL hNewDIBBits1;
  1479. LPSTR lpNewDIBBits2;
  1480. HLOCAL hNewDIBBits2;
  1481. //循环变量
  1482. long i;
  1483. long j;
  1484. // 模板高度
  1485. int iTempH;
  1486. // 模板宽度
  1487. int iTempW;
  1488. // 模板系数
  1489. FLOAT fTempC;
  1490. // 模板中心元素X坐标
  1491. int iTempMX;
  1492. // 模板中心元素Y坐标
  1493. int iTempMY;
  1494. //模板数组
  1495. FLOAT aTemplate[9];
  1496. // 暂时分配内存,以保存新图像
  1497. hNewDIBBits1 = LocalAlloc(LHND, lWidth * lHeight);
  1498. if (hNewDIBBits1 == NULL)
  1499. {
  1500. // 分配内存失败
  1501. return FALSE;
  1502. }
  1503. // 锁定内存
  1504. lpNewDIBBits1 = (char * )LocalLock(hNewDIBBits1);
  1505. // 暂时分配内存,以保存新图像
  1506. hNewDIBBits2 = LocalAlloc(LHND, lWidth * lHeight);
  1507. if (hNewDIBBits2 == NULL)
  1508. {
  1509. // 分配内存失败
  1510. return FALSE;
  1511. }
  1512. // 锁定内存
  1513. lpNewDIBBits2 = (char * )LocalLock(hNewDIBBits2);
  1514. // 拷贝源图像到缓存图像中
  1515. lpDst1 = (char *)lpNewDIBBits1;
  1516. memcpy(lpNewDIBBits1, lpDIBBits, lWidth * lHeight);
  1517. lpDst2 = (char *)lpNewDIBBits2;
  1518. memcpy(lpNewDIBBits2, lpDIBBits, lWidth * lHeight);
  1519. // 设置Prewitt模板参数
  1520. iTempW = 3;
  1521. iTempH = 3;
  1522. fTempC = 1.0;
  1523. iTempMX = 1;
  1524. iTempMY = 1;
  1525. aTemplate[0] = 0.0;
  1526. aTemplate[1] = 0.0;
  1527. aTemplate[2] = 0.0;
  1528. aTemplate[3] = -1.0;
  1529. aTemplate[4] = 1.0;
  1530. aTemplate[5] = 0.0;
  1531. aTemplate[6] = 0.0;
  1532. aTemplate[7] = 0.0;
  1533. aTemplate[8] = 0.0;
  1534. // 调用Template()函数
  1535. if (!Template(lpNewDIBBits1, lWidth, lHeight, 
  1536. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  1537. {
  1538. return FALSE;
  1539. }
  1540. // 设置Prewitt模板参数
  1541. aTemplate[0] = 0.0;
  1542. aTemplate[1] = -1.0;
  1543. aTemplate[2] = 0.0;
  1544. aTemplate[3] = 0.0;
  1545. aTemplate[4] = 1.0;
  1546. aTemplate[5] = 0.0;
  1547. aTemplate[6] = 0.0;
  1548. aTemplate[7] = 0.0;
  1549. aTemplate[8] = 0.0;
  1550. // 调用Template()函数
  1551. if (!Template(lpNewDIBBits2, lWidth, lHeight, 
  1552. iTempH, iTempW, iTempMX, iTempMY, aTemplate, fTempC))
  1553. {
  1554. return FALSE;
  1555. }
  1556. //求两幅缓存图像的最大值
  1557. for(j = 0; j <lHeight; j++)
  1558. {
  1559. for(i = 0;i <lWidth-1; i++)
  1560. {
  1561. // 指向缓存图像1倒数第j行,第i个象素的指针
  1562. lpDst1 = (char *)lpNewDIBBits1 + lWidth * j + i;
  1563. // 指向缓存图像2倒数第j行,第i个象素的指针
  1564. lpDst2 = (char *)lpNewDIBBits2 + lWidth * j + i;
  1565. if(*lpDst2 > *lpDst1)
  1566. *lpDst1 = *lpDst2;
  1567. }
  1568. }
  1569. // 复制经过模板运算后的图像到源图像
  1570. memcpy(lpDIBBits, lpNewDIBBits1, lWidth * lHeight);
  1571. // 释放内存
  1572. LocalUnlock(hNewDIBBits1);
  1573. LocalFree(hNewDIBBits1);
  1574. LocalUnlock(hNewDIBBits2);
  1575. LocalFree(hNewDIBBits2);
  1576. // 返回
  1577. return TRUE;
  1578. }