Steger.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. #include "Steger.h"
  2. #include <math.h>
  3. #include <vector>
  4. #include <chrono>
  5. const double PI = 3.1415926535897932;
  6. typedef CvPoint2D64f Point2d;
  7. std::vector<cv::Point2d> g_contour;
  8. static CvMat* M;
  9. static CvMat* E;
  10. static CvMat* I;
  11. double *fhx(double zita, int m)
  12. {
  13. int size = 2 * m + 1;
  14. double *pData = new double[size*size];
  15. for (int i = -m; i <= m; i++) {
  16. for (int j = -m; j <= m; j++) {
  17. pData[(i + m)*size + (j + m)] = -j / (zita*zita)*1.0 / (2.0*PI*zita*zita)*exp(-(i*i + j*j) / (2.0*zita*zita));
  18. }
  19. }
  20. return pData;
  21. }
  22. double *fhy(double zita, int m)
  23. {
  24. int size = 2 * m + 1;
  25. double *pData = new double[size*size];
  26. for (int i = -m; i <= m; i++) {
  27. for (int j = -m; j <= m; j++) {
  28. pData[(i + m)*size + (j + m)] = -i / (zita*zita)*1.0 / (2.0*PI*zita*zita)*exp(-(i*i + j*j) / (2.0*zita*zita));
  29. }
  30. }
  31. return pData;
  32. }
  33. double *fhxx(double zita, int m)
  34. {
  35. int size = 2 * m + 1;
  36. double *pData = new double[size*size];
  37. for (int i = -m; i <= m; i++) {
  38. for (int j = -m; j <= m; j++) {
  39. pData[(i + m)*size + (j + m)] = (j*j / pow(zita, 4) - 1.0 / (zita*zita))*1.0 / (2.0*PI*zita*zita)*exp(-(i*i + j*j) / (2.0*zita*zita));
  40. }
  41. }
  42. return pData;
  43. }
  44. double *fhyy(double zita, int m)
  45. {
  46. int size = 2 * m + 1;
  47. double *pData = new double[size*size];
  48. for (int i = -m; i <= m; i++) {
  49. for (int j = -m; j <= m; j++) {
  50. pData[(i + m)*size + (j + m)] = (i*i / pow(zita, 4) - 1.0 / (zita*zita))*1.0 / (2.0*PI*zita*zita)*exp(-(i*i + j*j) / (2.0*zita*zita));
  51. }
  52. }
  53. return pData;
  54. }
  55. double *fhxy(double zita, int m)
  56. {
  57. int size = 2 * m + 1;
  58. double *pData = new double[size*size];
  59. for (int i = -m; i <= m; i++) {
  60. for (int j = -m; j <= m; j++) {
  61. pData[(i + m)*size + (j + m)] = i*j / pow(zita, 4) * 1.0 / (2.0*PI*zita*zita)*exp(-(i*i + j*j) / (2.0*zita*zita));
  62. }
  63. }
  64. return pData;
  65. }
  66. void getSubdata(unsigned char *pData, int width, int h, int w, int m, unsigned char *tData)
  67. {
  68. int size = 2 * m + 1;
  69. for (int i = -m; i <= m; i++) {
  70. memcpy(tData + (i + m)*size, pData + (h + i)*width + w - m, size);
  71. }
  72. }
  73. double sum(unsigned char *pData, int width, int h, int w, double *mat, int m)
  74. {
  75. double s = 0.0;
  76. int size = (2 * m + 1)*(2 * m + 1);
  77. double *p = mat;
  78. unsigned char *q = pData;
  79. for (int i = size - 1; i >= 0; i--)
  80. s += (*p++) * (*q++);
  81. return s;
  82. }
  83. CSteger::CSteger(int width, int height)
  84. {
  85. m_width = width;
  86. m_height = height;
  87. m_pData = NULL;
  88. zita = 6 / sqrt(3.0); //6
  89. vThresh = 50;
  90. ftt_max2 = -1;
  91. h_size = (int)(2 * ceil(3 * zita - 1) + 1);
  92. h_N1 = (h_size - 1) / 2;
  93. hx = fhx(zita, h_N1);
  94. hy = fhy(zita, h_N1);
  95. hxx = fhxx(zita, h_N1);
  96. hxy = fhxy(zita, h_N1);
  97. hyy = fhyy(zita, h_N1);
  98. M = cvCreateMat(2, 2, CV_64FC1);
  99. E = cvCreateMat(2, 2, CV_64FC1);
  100. I = cvCreateMat(2, 1, CV_64FC1);
  101. }
  102. CSteger::~CSteger()
  103. {
  104. delete[] hx;
  105. delete[] hy;
  106. delete[] hxx;
  107. delete[] hyy;
  108. delete[] hxy;
  109. }
  110. void CSteger::Clear()
  111. {
  112. m_width = 0;
  113. m_height = 0;
  114. if (m_pData){
  115. delete[] m_pData;
  116. m_pData = NULL;
  117. }
  118. }
  119. void CSteger::SetSize(int width, int height, unsigned char *pData)
  120. {
  121. if (width != m_width || m_height != height) {
  122. Clear();
  123. m_width = width;
  124. m_height = height;
  125. m_pData = new unsigned char[m_width*m_height];
  126. }
  127. memcpy(m_pData, pData, m_width*m_height);
  128. }
  129. std::vector<cv::Point2d> CSteger::StripCenter(cv::Mat image)
  130. {
  131. auto t1=std::chrono::steady_clock::now();
  132. SetSize(image.cols, image.rows, (unsigned char *)image.data);
  133. unsigned char *tData = new unsigned char[h_size*h_size];
  134. int i, j;
  135. double gx, gy, gxx, gyy, gxy;
  136. cvZero(E);
  137. cvZero(I);
  138. int acc1 = 0, acc2 = 0;
  139. double nx, ny, fttmax, t;
  140. cv::Point2d pt;
  141. g_contour.clear();
  142. for (i = h_N1; i < m_height - h_N1; i++) {
  143. for (j = h_N1; j < m_width - h_N1; j++) {
  144. if (m_pData[i*m_width + j] > vThresh) {
  145. getSubdata(m_pData, m_width, i, j, h_N1, tData);
  146. gx = sum(tData, m_width, i, j, hx, h_N1);
  147. gy = sum(tData, m_width, i, j, hy, h_N1);
  148. gxx = sum(tData, m_width, i, j, hxx, h_N1);
  149. gxy = sum(tData, m_width, i, j, hxy, h_N1);
  150. gyy = sum(tData, m_width, i, j, hyy, h_N1);
  151. cvmSet(M, 0, 0, gxx);
  152. cvmSet(M, 0, 1, gxy);
  153. cvmSet(M, 1, 0, gxy);
  154. cvmSet(M, 1, 1, gyy);
  155. cvEigenVV(M, E, I);
  156. if (fabs(cvmGet(I, 0, 0)) > fabs(cvmGet(I, 1, 0))){
  157. nx = cvmGet(E, 0, 0);
  158. ny = cvmGet(E, 0, 1);
  159. fttmax = cvmGet(I, 0, 0);
  160. }
  161. else {
  162. nx = cvmGet(E, 1, 0);
  163. ny = cvmGet(E, 1, 1);
  164. fttmax = cvmGet(I, 1, 0);
  165. }
  166. t = -(nx*gx + ny*gy) / (nx*nx*gxx + 2 * nx*ny*gxy + ny*ny*gyy);
  167. if (fabs(t*nx) <= 0.5 && fabs(t*ny) <= 0.5 && fttmax<ftt_max2){
  168. pt.y = i + t*nx;
  169. pt.x = j + t*ny;
  170. //if(pt.x>400 && pt.x<2000 && pt.y>50 && pt.y<1900) {
  171. g_contour.push_back(pt);
  172. acc1++;
  173. //}
  174. }
  175. acc2++;
  176. }
  177. }
  178. }
  179. delete[] tData;
  180. auto t2=std::chrono::steady_clock::now();
  181. auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
  182. double tm=double(duration.count()) * std::chrono::milliseconds::period::num /
  183. std::chrono::milliseconds::period::den;
  184. printf("triangle time :%lfs\n",tm);
  185. return g_contour;
  186. }
  187. void CSteger::SaveImage(char *filename)
  188. {
  189. cv::Mat src = cv::Mat(cv::Size(m_width, m_height), 8, CV_8UC1);
  190. memcpy(src.data, m_pData, m_width*m_height);
  191. /*FILE *fp = fopen(".\\5.txt", "w");
  192. fprintf(fp, "%d\n", g_contour.size());
  193. int h, w;
  194. for (vector<cv::Point2d>::iterator it = g_contour.begin(); it != g_contour.end(); it++)
  195. {
  196. h = (int)((*it).x + 0.5);
  197. w = (int)((*it).y + 0.5);
  198. cvSet2D(src, h, w, cvScalar(0));
  199. fprintf(fp, "%lf\t%lf\n", (*it).x, (*it).y);
  200. }
  201. fclose(fp);
  202. */
  203. cv::imwrite(filename, src);
  204. }
  205. void CSteger::test(cv::Mat image, cv::Mat& out)
  206. {
  207. std::vector<cv::Point2d> points = StripCenter(image);
  208. cv::cvtColor(image,out,cv::COLOR_GRAY2RGB);
  209. for (int i = 0; i < points.size(); i++)
  210. {
  211. int x = int(points[i].x + 0.5);
  212. int y = int(points[i].y + 0.5);
  213. if (x < out.cols&&y < out.rows)
  214. cv::circle(out, points[i], 0.3, cv::Scalar(0, 0, 200));
  215. }
  216. }