edgecontour.cpp
上传用户:alisonmail
上传日期:2013-02-28
资源大小:500k
文件大小:38k
源码类别:

图片显示

开发平台:

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