utils.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. #pragma once
  2. #include <opencv2\imgproc\imgproc.hpp>
  3. //#include <boost\math\distributions\binomial.hpp>
  4. #include <vector>
  5. #include <time.h>
  6. #include <string>
  7. #include <numeric>
  8. #include "data_def_api.h"
  9. #include "data_def.h"
  10. //using namespace cv;
  11. using namespace std;
  12. namespace graft_cv{
  13. // convert ImgInfo to cv mat
  14. cv::Mat imginfo2mat(ImgInfo*);
  15. ImgInfo* mat2imginfo(const cv::Mat&);
  16. void imginfo_release(ImgInfo**);
  17. bool isvalid(const ImgInfo*);
  18. string currTime();
  19. string getImgId(int im_type);
  20. string getImgIdOa(string iid, int im_idx);
  21. inline void throw_msg(string& msg);
  22. // set bottom image rows_cnt rows to "value", for xiaoxu camera
  23. void image_set_bottom(cv::Mat& img,unsigned char value,int rows_cnt);
  24. void image_set_top(cv::Mat& img, unsigned char value, int rows_cnt);
  25. void image_draw_line(cv::Mat& img,int x0,int y0,int x1,int y1);
  26. // histogram
  27. void mat_histogram(
  28. cv::Mat&,
  29. vector<int>&hist,
  30. int axis=0,
  31. int r0=-1,
  32. int r1=-1,
  33. int c0=-1,
  34. int c1=-1
  35. );
  36. // weighted histogram
  37. void mat_histogram_w(
  38. cv::Mat& img,
  39. vector<int>&hist,
  40. int axis=0,
  41. int r0=-1,
  42. int r1=-1,
  43. int c0=-1,
  44. int c1=-1,
  45. bool asc_w=true //true---ascending weight with x/y coordinate, [0-1.0], false --- descending weight [1.0--0.0]
  46. );
  47. void mat_histogram_yfork(
  48. cv::Mat& img,
  49. vector<int>&hist,
  50. int r0,
  51. int r1
  52. );
  53. // histogram to image
  54. void hist2image(
  55. vector<int>& hist,
  56. cv::Mat&img,
  57. int aix=1,
  58. int grid_col=50,
  59. int grid_row=50
  60. );
  61. template<class T>
  62. void hist2image_line(
  63. vector<T>& hist,
  64. cv::Mat&img,
  65. int grid_col/*=50*/,
  66. int grid_row/*=50*/
  67. )
  68. {
  69. if(hist.size()<2){return;}
  70. vector<T>::iterator maxit = max_element(begin(hist),end(hist));
  71. if( grid_col<10){grid_col=10;}
  72. if( grid_row<10){grid_row=10;}
  73. img = Mat::zeros(*maxit,hist.size(), CV_8UC1);
  74. drawgrid(img,grid_col, grid_row,1);
  75. for(size_t i=1; i<hist.size();++i){
  76. line(img,Point(i-1,(int)*maxit - (int)hist[i-1]),Point(i,(int)*maxit - (int)hist[i]),Scalar(255));
  77. }
  78. };
  79. template<class T>
  80. void hist2image_scale_line(
  81. vector<T>& hist,
  82. cv::Mat&img,
  83. T ymin,
  84. T ymax,
  85. T yratio,//数值像素比,一个像素代表的数值量
  86. T th,
  87. int grid_col/*=50*/,
  88. int grid_row/*=50*/
  89. )
  90. {
  91. if(hist.size()<2){return;}
  92. if( grid_col<10){grid_col=10;}
  93. if( grid_row<10){grid_row=10;}
  94. int height =(int)((ymax-ymin)/yratio);
  95. img = cv::Mat::zeros(height,hist.size(), CV_8UC1);
  96. drawgrid(img,grid_col, grid_row,1);
  97. for(size_t i=1; i<hist.size();++i){
  98. int y_1 = height-(int)((hist[i-1]-ymin)/yratio);
  99. int y_0 = height-(int)((hist[i]-ymin)/yratio);
  100. cv::line(img, cv::Point(i-1,y_1), cv::Point(i,y_0), cv::Scalar(255));
  101. }
  102. int h1 = height-(int)((th-ymin)/yratio);
  103. int h2 = height-(int)((1.0/th-ymin)/yratio);
  104. cv::line(img, cv::Point(0,h1), cv::Point(hist.size()-1,h1), cv::Scalar(200));
  105. cv::line(img, cv::Point(0,h2), cv::Point(hist.size()-1,h2), cv::Scalar(200));
  106. };
  107. void drawgrid(
  108. cv::Mat&img,
  109. int grid_col=50,
  110. int grid_row=50,
  111. int line_thick=1
  112. );
  113. //r2 index calculation for line regression
  114. // y = beta0 + beta1 * x
  115. template<class T>
  116. double r2index(
  117. const vector<T>& x,
  118. const vector<T>& y,
  119. size_t i0,
  120. size_t i1,
  121. double& beta0,
  122. double& beta1)
  123. {
  124. double r2 = 0.0;
  125. assert(x.size() == y.size());
  126. assert(i0<i1);
  127. assert(i1-i0>1);
  128. assert(i0>=0 && i1<y.size());
  129. // y = beta0 + beta1 * x
  130. //double beta0=0, beta1=0;
  131. double t1=0, t2=0,t3=0,t4=0;
  132. double n = (double)(i1-i0+1);
  133. for(size_t i=i0; i<=i1; ++i)
  134. {
  135. t1 += (double)x[i] * (double)x[i];
  136. t2 += (double)x[i];
  137. t3 += (double)x[i] * (double)y[i];
  138. t4 += (double)y[i];
  139. }
  140. beta0 = (t1*t4 - t2*t3) / (t1*n - t2*t2);
  141. beta1 = (t3*n - t2*t4) / (t1*n -t2*t2);
  142. double sst=0, ssr=0, sse=0;
  143. double y_mu = t4/n;
  144. double y_hat;
  145. for(size_t i=i0; i<=i1; ++i)
  146. {
  147. y_hat = beta0 + beta1*(double)x[i];
  148. ssr += (y_hat - y_mu)*(y_hat - y_mu);
  149. sse += ((double)y[i] - y_hat)* ((double)y[i] - y_hat);
  150. }
  151. sst = ssr + sse;
  152. r2 = 1.0 - sse/sst;
  153. return r2;
  154. };
  155. void get_stem_x_range_oa(
  156. const vector<int>& hist_h,
  157. double h_ratio,
  158. int padding,
  159. int cent_x,
  160. int width_x,
  161. int&x0,
  162. int&x1,
  163. int&stem_x0,
  164. int&stem_x1
  165. );
  166. void get_stem_x_range_rscut(
  167. const vector<int>& hist_h,
  168. double h_ratio,
  169. int padding,
  170. int cent_x,
  171. int width_x,
  172. int&x0,
  173. int&x1,
  174. int&stem_x0,
  175. int&stem_x1
  176. );
  177. void get_stem_x_range_scion(
  178. const vector<int>& hist_h,
  179. double h_ratio,
  180. int padding,
  181. int&x0,
  182. int&x1,
  183. int&stem_x0,
  184. int&stem_x1
  185. );
  186. ////////////////////////////////////////////////////////////////////////
  187. // y-fork detect
  188. void get_stem_y_fork(
  189. const vector<int>& hist,
  190. double ratio,
  191. int stem_dia_min,
  192. int stem_fork_y_min,
  193. double stem_dia_mp,
  194. int& fork_y, //output, 茎分叉y像素位置
  195. int& end_y, //output,茎根部y像素位置
  196. int& stem_dia //output, end_y和fork_y间茎粗
  197. );
  198. void get_stem_y_fork_rs(
  199. const vector<int>& hist,
  200. double ratio,
  201. int stem_dia_min,
  202. int stem_fork_y_min,
  203. double stem_dia_mp,
  204. int& fork_y, //output
  205. int& end_y, //output
  206. int& stem_dia, //output
  207. int& roi_max_y //output
  208. );
  209. void get_stem_y_fork_rs_update(
  210. const cv::Mat& bin_img,
  211. int stem_x_padding,
  212. int x0,
  213. int x1,
  214. int max_y,
  215. int stem_root_y,
  216. int stem_dia,
  217. bool image_show,
  218. double cut_point_offset_ratio,
  219. cv::Point& fork_cent,
  220. double& max_radius,
  221. double& stem_angle
  222. );
  223. double yfork_validity_position(
  224. int max_y,
  225. int end_y,
  226. int fork_y);
  227. double yfork_validity_stemdiaratio(
  228. int stem_dia,
  229. int dia_y,
  230. double opt_dia_ratio);
  231. void yfork_validity_stemdiachange(
  232. const vector<int>& hist,
  233. int stem_dia_min,
  234. vector<double>& var_ratio
  235. );
  236. //通过计算茎均值,运用统计过程控制方法检测显著点
  237. void get_stem_y_fork_3sigma(
  238. const vector<int>& hist,
  239. double ratio,
  240. int stem_dia_min,
  241. int stem_fork_y_min,
  242. double stem_dia_mp,
  243. int& fork_y, //output, 茎分叉y像素位置
  244. int& end_y, //output,茎根部y像素位置
  245. int& stem_dia //output, end_y和fork_y间茎粗
  246. );
  247. double stem_y_fork_validity(
  248. const vector<int>& hist,
  249. int fork_y,
  250. int end_y);
  251. void get_hist_segment(
  252. const vector<int>& hist,
  253. int threshold,
  254. vector<gcv_point<int>>& segments
  255. );
  256. void get_hist_mean_var_local(
  257. const vector<int>& hist,
  258. int x0,
  259. int x1,
  260. double& mean,
  261. double& var
  262. );
  263. //void get_stem_y_index(
  264. // Mat& bin_img,
  265. // int x0,
  266. // int x1,
  267. // int stem_dia_min,
  268. // int stem_fork_y_min,
  269. // double stem_dia_mp,
  270. // int& fork_y, //output
  271. // int& end_y, //output
  272. // int& stem_dia //output
  273. //);
  274. void imshow_wait(
  275. const char* winname,
  276. cv::Mat&,
  277. int waittype=-1
  278. );
  279. int get_stem_fork_right(
  280. cv::Mat&stem_img,
  281. int stem_fork_y,
  282. int stem_x0,
  283. int stem_x1,
  284. int detect_window);
  285. int get_stem_fork_left(
  286. cv::Mat&stem_img,
  287. int stem_fork_y,
  288. int stem_x0,
  289. int stem_x1,
  290. int detect_window);
  291. void get_stem_fork_xs(
  292. cv::Mat&stem_img,
  293. int stem_fork_y,
  294. int stem_x0,
  295. int stem_x1,
  296. int x0,
  297. int x1,
  298. int & fork_x0,
  299. int & fork_x1
  300. );
  301. void get_next_pt(
  302. cv::Mat& edge_img,
  303. gcv_point<int>&start_pt,
  304. gcv_point<int>&pre_pt,
  305. gcv_point<int>&nxt_pt, //output
  306. bool is_up=true);
  307. // 二次曲线拟合,返回二次曲线对称轴x的坐标
  308. double qua_fitting(vector<double>&xx, vector<double>&yy);
  309. template <typename T>
  310. vector<size_t> sort_indexes_e(vector<T> &v, bool ascending=true)
  311. {
  312. vector<size_t> idx(v.size());
  313. iota(idx.begin(), idx.end(), 0);
  314. if(ascending){
  315. sort(idx.begin(), idx.end(),
  316. [&v](size_t i1, size_t i2) {return v[i1] < v[i2]; });
  317. }
  318. else{
  319. sort(idx.begin(), idx.end(),
  320. [&v](size_t i1, size_t i2) {return v[i1] > v[i2]; });
  321. }
  322. return idx;
  323. }
  324. template<typename T>
  325. void hist_filter(vector<T>& hist, int method=0, int radius=2)
  326. {
  327. //mothod: 0---mid; 1--mean
  328. assert(radius>=1);
  329. if(hist.size()<3){return;}
  330. vector<T>tmp;
  331. if(method==0){
  332. T* buff = new T[2+2*radius];
  333. for(int i=0; i<hist.size();++i){
  334. int cnt=0;
  335. for(int r = -radius;r<=radius;++r){
  336. int idx=i+r;
  337. if(idx<0 || idx>=hist.size()){continue;}
  338. buff[cnt++]=hist[idx];
  339. }
  340. sort(buff,buff+cnt);
  341. int cent = cnt/2;
  342. tmp.push_back(buff[cent]);
  343. }
  344. delete []buff;
  345. }
  346. if(method==1){
  347. for(int i=0; i<hist.size();++i){
  348. int cnt=0;
  349. T mean = T(0);
  350. for(int r = -radius;r<=radius;++r){
  351. int idx=i+r;
  352. if(idx<0 || idx>=hist.size()){continue;}
  353. mean+=hist[idx];
  354. }
  355. mean =mean/cnt;
  356. tmp.push_back(mean);
  357. }
  358. }
  359. for(size_t j=0;j<hist.size();++j){hist[j]=tmp[j];}
  360. }
  361. template<typename T>
  362. double otsu(vector<T>&data)
  363. {
  364. if (data.size() == 0) {
  365. return 0.0;
  366. }
  367. std::vector<T>data_sort(data);
  368. std::sort(data_sort.begin(), data_sort.end());
  369. double t0 = data_sort[int(data_sort.size() / 2)];
  370. double t1 = data_sort.back();
  371. double t = t0;
  372. double max_g = 0;
  373. double max_t = t0;
  374. std::vector<T>d0;
  375. std::vector<T>d1;
  376. double n = data.size();
  377. while (t < t1) {
  378. d0.clear();
  379. d1.clear();
  380. for (auto& v : data_sort) {
  381. if (v < t) { d0.push_back(v); }
  382. else { d1.push_back(v); }
  383. }
  384. double g = get_hist_mean(d0) - get_hist_mean(d1);
  385. g *= g;
  386. g = g* d0.size() * d1.size() / n / n;
  387. if (g > max_g) {
  388. max_g = g;
  389. max_t = t;
  390. }
  391. t += 1;
  392. }
  393. return max_t;
  394. }
  395. template<typename T>
  396. double get_hist_mean(vector<T>&data) {
  397. double mu = 0;
  398. for (auto &v : data) { mu += v; }
  399. if (data.size() > 0) {
  400. mu /= data.size();
  401. }
  402. return mu;
  403. }
  404. template<typename T>
  405. double get_hist_std(vector<T>&data, T mu) {
  406. double std_v = 0;
  407. for (auto &v : data) { std_v += (v-mu)*(v - mu); }
  408. if (data.size() > 0) {
  409. std_v /= data.size();
  410. std_v = sqrt(std_v);
  411. }
  412. return std_v;
  413. }
  414. template<typename T>
  415. int trend_detect_pos(const vector<T>&data, int data_th, int step=15) {
  416. int pos = -1;
  417. if (data.size() < 2 * step) {
  418. return pos;
  419. }
  420. int radius = int(step/2);
  421. boost::math::binomial_distribution<> binomal(radius, 0.5);
  422. pos = radius;
  423. int max_v = 0;
  424. int pos_n, neg_n;
  425. for (size_t i = radius; i < data.size() - radius; ++i) {
  426. pos_n = neg_n = 0;
  427. for (int j = 1; j <= radius; ++j) {
  428. int diff = data[i + j] - data[i + j -radius];
  429. if (diff > 0) {
  430. pos_n++;
  431. }
  432. else {
  433. neg_n++;
  434. }
  435. }
  436. int k = min(pos_n, neg_n);
  437. double p = 2.0 * boost::math::cdf(binomal, k);
  438. std::cout <<"idx="<<i<< ", posn=" << pos_n << ", negn=" << neg_n << ", pvalue=" << p << endl;
  439. if (p > 0.05) {
  440. if(fabs(data.at(i) - data_th)<3)
  441. {
  442. pos = i;
  443. break;
  444. }
  445. }
  446. }
  447. return pos;
  448. }
  449. //nms
  450. int nms_bbox(
  451. vector<Bbox>& candidate_droplets, //input
  452. float th, //input
  453. vector<int>& keep //output
  454. );
  455. //iou
  456. float iou_bbox(
  457. const Bbox & det_a,
  458. const Bbox & det_b);
  459. };