使用的darknet实现区域人头统计、目标跟踪

使用的darknet实现区域人头统计、目标跟踪 风清扬 2023-07-06 09:53:53 887

该功能使用的darknet框架,训练的yolo-tiny人头模型,之后使用opencv4.5.1版本调用的yolo-tiny模型,跟踪使用KCF跟踪算法,整体上实现了三个功能:

1、区域内的人头统计;

2、区域内的绊线检测功能;

3、区域内目标跟踪,统计人头数量的功能。

一、网址:https://github.com/AlexeyAB/darknet

二、参考训练参考我的另两篇博客:

Darknet下的Yolo v3_dragon_perfect的博客-CSDN博客

深度学习 客流统计 人流计数dragon_perfect的博客-CSDN博客人流统计算法

跟踪部分的代码如下:

  1. #pragma once
  2. #include "HeadDetect.h"
  3. #include "opencv2/opencv.hpp"
  4. #include "KCFLib/kcftracker.hpp"
  5. using namespace cv;
  6. using namespace std;
  7. #define MAX_TRACK_COUNT 100//目标的最大个数
  8. #define MAX_TRAJECTORY_COUNT 200//目标轨迹的最大个数
  9. #define MAX_MISS_FRAME 10//最大丢失帧数
  10. #define MAX_MATCH_FRAME 3//最大匹配帧数
  11. #define MAX_TRACK_DIST 40000//最大跟踪距离
  12. struct ZTracker
  13. {
  14. int nID;
  15. int nMissTimes;
  16. bool bMatchID;
  17. bool bTrack;
  18. bool bStatOK;
  19. bool bInitDirection;
  20. int nInitDirection;
  21. cv::KalmanFilter *kf;
  22. cv::Point predPoint;
  23. cv::Point curCentre;
  24. cv::Rect curRect;
  25. int nTrajCount;
  26. cv::Point centres[MAX_TRAJECTORY_COUNT];
  27. cv::Rect blobs[MAX_TRAJECTORY_COUNT];
  28. };
  29. class ZHeadTrack
  30. {
  31. public:
  32. ZHeadTrack();
  33. ~ZHeadTrack();
  34. int m_InCount;
  35. int m_OutCount;
  36. int m_RegionCount;
  37. ZTracker *m_pTrackers;
  38. KCFTracker m_pKCF[MAX_TRACK_COUNT];
  39. void trackInitial(cv::Point arrowStart, cv::Point arrowEnd, cv::Point lineStart, cv::Point lineEnd, vector<Point> regionPonits,int width,int height);
  40. void trackProcess(HDBox_Container *pHDBox_Container, HDRect *rect,bool bMask);
  41. void kcfProcess(HDBox_Container *pHDBox_Container, HDRect *rect, cv::Mat image);
  42. void trackInOutStatistics();
  43. void trackRegionStatistics();
  44. int pointInLineSide(cv::Point point, cv::Point lineStart, cv::Point lineEnd);
  45. float CalculateIou(cv::Rect& det, cv::Rect& track);
  46. public:
  47. int m_trackID;
  48. int m_nArrowStart;
  49. int m_nArrowEnd;
  50. cv::Point m_lineStart;
  51. cv::Point m_lineEnd;
  52. cv::Mat m_detectRegion;
  53. HDBox_Container m_boxContainer;
  54. HDTracker_Region m_trackeRegion;
  55. };
  1. #include "HeadTrack.h"
  2. ZHeadTrack::ZHeadTrack()
  3. {
  4. m_trackID = 0;
  5. m_InCount = 0;
  6. m_OutCount = 0;
  7. m_RegionCount = 0;
  8. m_nArrowStart = 0;
  9. m_nArrowEnd = 0;
  10. m_pTrackers = new ZTracker[MAX_TRACK_COUNT];
  11. memset(m_pTrackers, 0, sizeof(ZTracker));
  12. }
  13. ZHeadTrack::~ZHeadTrack()
  14. {
  15. delete m_pTrackers;
  16. }
  17. void ZHeadTrack::trackInitial(cv::Point arrowStart, cv::Point arrowEnd, cv::Point lineStart, cv::Point lineEnd, vector<Point> regionPonits, int width, int height)
  18. {
  19. m_trackID = 0;
  20. m_InCount = 0;
  21. m_OutCount = 0;
  22. m_nArrowStart = pointInLineSide(arrowStart, lineStart, lineEnd);
  23. m_nArrowEnd = pointInLineSide(arrowEnd, lineStart, lineEnd);
  24. m_lineStart = lineStart;
  25. m_lineEnd = lineEnd;
  26. vector<vector<Point>> vpts;
  27. vpts.push_back(regionPonits);
  28. cv::Mat detectRegion = cv::Mat::zeros(height, width, CV_8UC3);
  29. cv::fillPoly(detectRegion, vpts, cv::Scalar(255, 255, 255));
  30. cv::cvtColor(detectRegion, m_detectRegion, COLOR_BGR2GRAY);
  31. //m_detectRegion = detectRegion.clone();
  32. //cv::imshow("detectRegion", m_detectRegion);
  33. //cv::waitKey(0);
  34. }
  35. void ZHeadTrack::trackProcess(HDBox_Container *pHDBox_Container, HDRect *rect, bool bMask)
  36. {
  37. int i = 0, j = 0;
  38. //把太小的rect删除
  39. m_boxContainer.headCount = 0;
  40. int width = m_detectRegion.cols;
  41. uchar *pDetectData = m_detectRegion.data;
  42. int step1 = m_detectRegion.step1();
  43. //cv::imshow("m_detectRegion", m_detectRegion);
  44. //cv::waitKey(10);
  45. for (i = 0;i< pHDBox_Container->headCount;i++)
  46. {
  47. HDRect *pHDRect = &pHDBox_Container->candidates[i];
  48. int nx = (pHDRect->right + pHDRect->left) / 2;
  49. int ny = (pHDRect->top + pHDRect->bottom) / 2;
  50. int rectW = pHDRect->right - pHDRect->left;
  51. int rectH = pHDRect->bottom - pHDRect->top;
  52. if (bMask)
  53. {
  54. if (rectW > 60 && rectH > 60 && (*(pDetectData + ny*width + nx) == 255))
  55. {
  56. m_boxContainer.candidates[m_boxContainer.headCount++] = pHDBox_Container->candidates[i];
  57. }
  58. }
  59. else
  60. {
  61. if (rectW > 40 && rectH > 40 && nx > rect->left && nx < rect->right && ny > rect->top && ny < rect->bottom)
  62. {
  63. m_boxContainer.candidates[m_boxContainer.headCount++] = pHDBox_Container->candidates[i];
  64. }
  65. }
  66. }
  67. bool bMatch[HD_MAX_HEADS] = { false };
  68. for (i = 0;i< m_boxContainer.headCount;i++)
  69. {
  70. bMatch[i] = false;
  71. }
  72. for (i = 0; i < MAX_TRACK_COUNT; i++)
  73. {
  74. ZTracker *pTracker = &m_pTrackers[i];
  75. if (pTracker->bTrack)
  76. {
  77. bool bMinst = false;
  78. int nMatchID = -1;
  79. int maxDist = MAX_TRACK_DIST;
  80. for (j = 0; j < m_boxContainer.headCount; j++)
  81. {
  82. if (!bMatch[j])
  83. {
  84. HDRect *pHDRect = &m_boxContainer.candidates[j];
  85. cv::Rect curRect;
  86. curRect.x = pHDRect->left;
  87. curRect.y = pHDRect->top;
  88. curRect.width = pHDRect->right - pHDRect->left;
  89. curRect.height = pHDRect->bottom - pHDRect->top;
  90. int nx = (pHDRect->left + pHDRect->right) / 2;
  91. int ny = (pHDRect->top + pHDRect->bottom) / 2;
  92. int dist = (pTracker->predPoint.x - nx)*(pTracker->predPoint.x - nx) + (pTracker->predPoint.y - ny)*(pTracker->predPoint.y - ny);
  93. if (dist < maxDist)
  94. {
  95. maxDist = dist;
  96. pTracker->curRect = curRect;//后面更新用
  97. pTracker->curCentre.x = nx;
  98. pTracker->curCentre.y = ny;
  99. nMatchID = j;
  100. bMinst = true;
  101. }
  102. }
  103. }
  104. //找到了blob
  105. if (bMinst)
  106. {
  107. bMatch[nMatchID] = true;
  108. HDRect *pHDRect = &m_boxContainer.candidates[nMatchID];
  109. cv::Rect curRect;
  110. curRect.x = pHDRect->left;
  111. curRect.y = pHDRect->top;
  112. curRect.width = pHDRect->right - pHDRect->left;
  113. curRect.height = pHDRect->bottom - pHDRect->top;
  114. int nx = (pHDRect->left + pHDRect->right) / 2;
  115. int ny = (pHDRect->top + pHDRect->bottom) / 2;
  116. pTracker->bMatchID = true;
  117. pTracker->nMissTimes = 0;
  118. pTracker->curCentre.x = nx;
  119. pTracker->curCentre.y = ny;
  120. pTracker->curRect = curRect;
  121. //更新预测值
  122. Mat measurement = Mat::zeros(2, 1, CV_32F);
  123. measurement.at<float>(0) = (float)nx;
  124. measurement.at<float>(1) = (float)ny;
  125. pTracker->kf->correct(measurement);
  126. Mat prediction = pTracker->kf->predict();
  127. pTracker->predPoint = Point(prediction.at<float>(0), prediction.at<float>(1)); //预测值(x',y')
  128. cv::Point centre = pTracker->centres[pTracker->nTrajCount - 1];
  129. if ((centre.x - nx)*(centre.x - nx) + (centre.y - ny)*(centre.y - ny) > 30)
  130. {
  131. pTracker->centres[pTracker->nTrajCount].x = nx;
  132. pTracker->centres[pTracker->nTrajCount].y = ny;
  133. pTracker->blobs[pTracker->nTrajCount] = curRect;
  134. pTracker->nTrajCount++;
  135. if (pTracker->nTrajCount >= MAX_TRAJECTORY_COUNT - 1)
  136. {
  137. pTracker->nTrajCount = MAX_TRAJECTORY_COUNT - 1;
  138. for (int k = 1; k < pTracker->nTrajCount; k++)
  139. {
  140. pTracker->centres[k - 1] = pTracker->centres[k];
  141. pTracker->blobs[k - 1] = pTracker->blobs[k];
  142. }
  143. }
  144. }
  145. }
  146. else//没找到blob
  147. {
  148. pTracker->nMissTimes++;
  149. //Mat prediction = pTracker->kf->predict();
  150. //pTracker->predPoint = Point(prediction.at<float>(0), prediction.at<float>(1)); //预测值(x',y')
  151. //更新预测值
  152. Mat measurement = Mat::zeros(2, 1, CV_32F);
  153. measurement.at<float>(0) = (float)pTracker->curCentre.x;
  154. measurement.at<float>(1) = (float)pTracker->curCentre.y;
  155. pTracker->kf->correct(measurement);
  156. Mat prediction = pTracker->kf->predict();
  157. pTracker->predPoint = Point(prediction.at<float>(0), prediction.at<float>(1)); //预测值(x',y')
  158. if (pTracker->nMissTimes > MAX_MISS_FRAME)
  159. {
  160. pTracker->bTrack = false;
  161. delete pTracker->kf;
  162. }
  163. }
  164. }
  165. }
  166. //没有匹配上的,需要重新创建目标
  167. for (i = 0; i < m_boxContainer.headCount; i++)
  168. {
  169. HDRect *pHDRect = &m_boxContainer.candidates[i];
  170. cv::Rect curRect;
  171. curRect.x = pHDRect->left;
  172. curRect.y = pHDRect->top;
  173. curRect.width = pHDRect->right - pHDRect->left;
  174. curRect.height = pHDRect->bottom - pHDRect->top;
  175. int nx = (pHDRect->left + pHDRect->right) / 2;
  176. int ny = (pHDRect->top + pHDRect->bottom) / 2;
  177. if (!bMatch[i])
  178. {
  179. for (j = 0; j < MAX_TRACK_COUNT; j++)
  180. {
  181. ZTracker *pTracker = &m_pTrackers[j];
  182. if (!pTracker->bTrack)
  183. {
  184. pTracker->bTrack = true;
  185. pTracker->bMatchID = true;
  186. pTracker->bStatOK = false;
  187. pTracker->bInitDirection = false;
  188. pTracker->nID = ++m_trackID;
  189. pTracker->curCentre.x = nx;
  190. pTracker->curCentre.y = ny;
  191. pTracker->curRect = curRect;
  192. pTracker->nMissTimes = 0;
  193. pTracker->predPoint.x = nx;
  194. pTracker->predPoint.y = ny;
  195. pTracker->kf = new cv::KalmanFilter(4, 2, 0);
  196. pTracker->kf->transitionMatrix = (Mat_<float>(4, 4) << 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1);//转移矩阵A
  197. cv::setIdentity(pTracker->kf->measurementMatrix); //测量矩阵H
  198. cv::setIdentity(pTracker->kf->processNoiseCov, Scalar::all(1e-5)); //系统噪声方差矩阵Q
  199. cv::setIdentity(pTracker->kf->measurementNoiseCov, Scalar::all(1e-1));//测量噪声方差矩阵R
  200. cv::setIdentity(pTracker->kf->errorCovPost, Scalar::all(1)); //后验错误估计协方差矩阵P
  201. pTracker->kf->statePost = (Mat_<float>(4, 1) << nx, ny, 0, 0);
  202. Mat prediction = pTracker->kf->predict();
  203. pTracker->predPoint = Point(prediction.at<float>(0), prediction.at<float>(1)); //预测值(x',y')
  204. pTracker->centres[0].x = nx;
  205. pTracker->centres[0].y = ny;
  206. pTracker->blobs[0] = curRect;
  207. pTracker->nTrajCount = 1;
  208. break;
  209. }
  210. }
  211. }
  212. }
  213. }
  214. float ZHeadTrack::CalculateIou(cv::Rect& det, cv::Rect& track)
  215. {
  216. // get min/max points
  217. auto xx1 = std::max(det.tl().x, track.tl().x);
  218. auto yy1 = std::max(det.tl().y, track.tl().y);
  219. auto xx2 = std::min(det.br().x, track.br().x);
  220. auto yy2 = std::min(det.br().y, track.br().y);
  221. auto w = std::max(0, xx2 - xx1);
  222. auto h = std::max(0, yy2 - yy1);
  223. // calculate area of intersection and union
  224. float det_area = det.area();
  225. float trk_area = track.area();
  226. auto intersection_area = w * h;
  227. float union_area = det_area + trk_area - intersection_area;
  228. auto iou = intersection_area / union_area;
  229. return iou;
  230. }
  231. void ZHeadTrack::kcfProcess(HDBox_Container *pHDBox_Container, HDRect *rect,cv::Mat image)
  232. {
  233. int i = 0, j = 0;
  234. //HDBox_Container container;
  235. m_boxContainer.headCount = 0;
  236. for (i = 0; i < pHDBox_Container->headCount; i++)
  237. {
  238. HDRect *pHDRect = &pHDBox_Container->candidates[i];
  239. int nx = (pHDRect->right + pHDRect->left) / 2;
  240. int ny = (pHDRect->top + pHDRect->bottom) / 2;
  241. int rectW = pHDRect->right - pHDRect->left;
  242. int rectH = pHDRect->bottom - pHDRect->top;
  243. if (rectW > 20 && rectH > 20 && nx > rect->left && nx < rect->right && ny > rect->top && ny < rect->bottom)
  244. {
  245. m_boxContainer.candidates[m_boxContainer.headCount++] = pHDBox_Container->candidates[i];
  246. }
  247. }
  248. bool bMatch[HD_MAX_HEADS] = { false };
  249. for (i = 0; i < m_boxContainer.headCount; i++)
  250. {
  251. bMatch[i] = false;
  252. }
  253. for (i = 0; i < MAX_TRACK_COUNT; i++)
  254. {
  255. KCFTracker *pKCF = &m_pKCF[i];
  256. if (pKCF->bTrack)
  257. {
  258. cv::Rect tRect = pKCF->update(image);
  259. pKCF->nTrackTimes++;
  260. pKCF->curRect = tRect;
  261. int nx = tRect.x + tRect.width / 2;
  262. int ny = tRect.y + tRect.height / 2;
  263. int dist = 10000000;
  264. float dfiou = 0.4;
  265. cv::Rect roiRect;
  266. int nFlag = 0;
  267. bool bOK = false;
  268. int nlimit = 0.6*std::sqrt(tRect.width*tRect.width + tRect.height*tRect.height);
  269. for (j = 0; j < m_boxContainer.headCount; j++)
  270. {
  271. HDRect *pHDRect = &m_boxContainer.candidates[j];
  272. int x0 = (pHDRect->left + pHDRect->right) / 2;
  273. int y0 = (pHDRect->top + pHDRect->bottom) / 2;
  274. int tempDist = std::sqrt((nx - x0)*(nx - x0) + (ny - y0)*(ny - y0));
  275. cv::Rect trackR;
  276. trackR.x = pHDRect->left;
  277. trackR.y = pHDRect->top;
  278. trackR.width = pHDRect->right - pHDRect->left;
  279. trackR.height = pHDRect->bottom - pHDRect->top;
  280. float fiou = CalculateIou(tRect, trackR);
  281. if (fiou > dfiou)
  282. {
  283. dfiou = fiou;
  284. nFlag = j;
  285. bOK = true;
  286. roiRect = trackR;
  287. }
  288. }
  289. if (bOK)
  290. {
  291. bMatch[nFlag] = true;
  292. pKCF->nMissFrame = 0;
  293. pKCF->init(roiRect, image);
  294. pKCF->curRect = roiRect;
  295. pKCF->nMatchTimes++;
  296. if (!pKCF->bValid)
  297. {
  298. if (/*pKCF->nMatchTimes > MAX_MATCH_FRAME && */pKCF->nTrackTimes == pKCF->nMatchTimes)
  299. {
  300. pKCF->bValid = true;
  301. pKCF->nID = ++m_trackID;
  302. }
  303. else
  304. {
  305. pKCF->bTrack = false;
  306. pKCF->bValid = false;
  307. }
  308. }
  309. }
  310. else
  311. {
  312. pKCF->nMissFrame++;
  313. if (pKCF->nMissFrame > MAX_MISS_FRAME)
  314. {
  315. pKCF->bTrack = false;
  316. pKCF->bValid = false;
  317. }
  318. }
  319. }
  320. }
  321. for (j = 0; j < m_boxContainer.headCount; j++)
  322. {
  323. if (!bMatch[j])
  324. {
  325. HDRect *pHDRect = &m_boxContainer.candidates[j];
  326. for (i = 0; i < MAX_TRACK_COUNT; i++)
  327. {
  328. KCFTracker *pKCF = &m_pKCF[i];
  329. if (!pKCF->bTrack)
  330. {
  331. pKCF->nID = -1;// ++m_trackID;
  332. pKCF->nMissFrame = 0;
  333. pKCF->nTrackTimes = 0;
  334. pKCF->nMatchTimes = 0;
  335. pKCF->bValid = false;
  336. cv::Rect roiRect;
  337. roiRect.x = pHDRect->left;
  338. roiRect.y = pHDRect->top;
  339. roiRect.width = pHDRect->right - pHDRect->left;
  340. roiRect.height = pHDRect->bottom - pHDRect->top;
  341. pKCF->bTrack = true;
  342. pKCF->init(roiRect, image);
  343. break;
  344. }
  345. }
  346. }
  347. }
  348. }
  349. int ZHeadTrack::pointInLineSide(cv::Point point, cv::Point lineStart, cv::Point lineEnd)
  350. {
  351. int x0 = 0, x1 = 0;
  352. int y0 = 0, y1 = 0;
  353. int v0 = 0, v1 = 0;
  354. bool bFlag = false;
  355. bool bFlagX = false;
  356. bool bFlagY = false;
  357. x0 = lineStart.x;
  358. x1 = lineEnd.x;
  359. y0 = lineStart.y;
  360. y1 = lineEnd.y;
  361. 先保证点在线段内
  362. if (x0 > x1)
  363. {
  364. bFlagX = point.x > x1 && point.x < x0;
  365. }
  366. else
  367. {
  368. bFlagX = point.x <x1 && point.x >x0;
  369. }
  370. if (y0 > y1)
  371. {
  372. bFlagY = point.y > y1 && point.y < y0;
  373. }
  374. else
  375. {
  376. bFlagY = point.y <y1 && point.y >y0;
  377. }
  378. bFlag = bFlagX || bFlagY;
  379. if (!bFlag)
  380. {
  381. return 0;
  382. }
  383. v0 = (point.x - x0)*(y1 - y0) - (point.y - y0)*(x1 - x0);
  384. v1 = x1 - x0;
  385. if (x1 - x0 == 0)
  386. {
  387. if (v0 < 0)
  388. {
  389. return -1;
  390. }
  391. else
  392. {
  393. return 1;
  394. }
  395. }
  396. else
  397. {
  398. if (v0*v1 < 0)
  399. {
  400. return -1;
  401. }
  402. else
  403. {
  404. return 1;
  405. }
  406. }
  407. return 0;
  408. }
  409. void ZHeadTrack::trackInOutStatistics()
  410. {
  411. int i = 0, j = 0;
  412. for (i = 0; i < MAX_TRACK_COUNT; i++)
  413. {
  414. ZTracker *pTracker = &m_pTrackers[i];
  415. if (pTracker->bTrack && pTracker->nTrajCount > 20 && !pTracker->bStatOK)
  416. {
  417. 连续确认跟踪起始点的方向
  418. if (!pTracker->bInitDirection)
  419. {
  420. int count0 = 0;
  421. for (j = 0; j < 10; j++)
  422. {
  423. int flag = pointInLineSide(pTracker->centres[j], m_lineStart, m_lineEnd);
  424. count0 += flag;
  425. }
  426. if (count0 > 0)
  427. {
  428. pTracker->nInitDirection = 1;
  429. }
  430. else
  431. {
  432. pTracker->nInitDirection = -1;
  433. }
  434. }
  435. 跟踪过线需要连续确认
  436. int count1 = 0;
  437. for (j = pTracker->nTrajCount - 10; j < pTracker->nTrajCount - 1; j++)
  438. {
  439. int flag = pointInLineSide(pTracker->centres[j], m_lineStart, m_lineEnd);
  440. if (flag != 0 && pTracker->nInitDirection != flag)
  441. {
  442. count1++;
  443. }
  444. }
  445. if (count1 > 6)
  446. {
  447. if (pTracker->nInitDirection == m_nArrowStart)
  448. {
  449. m_InCount++;
  450. }
  451. else
  452. {
  453. m_OutCount++;
  454. }
  455. pTracker->bStatOK = true;
  456. }
  457. }
  458. }
  459. }
  460. void ZHeadTrack::trackRegionStatistics()
  461. {
  462. int i = 0, j = 0;
  463. m_trackeRegion.currentCount = 0;
  464. for (i = 0; i < MAX_TRACK_COUNT; i++)
  465. {
  466. ZTracker *pTracker = &m_pTrackers[i];
  467. if (pTracker->bTrack && pTracker->nTrajCount > 5 && !pTracker->bStatOK)
  468. {
  469. m_trackeRegion.rect[m_trackeRegion.currentCount].id = pTracker->nID;
  470. m_trackeRegion.rect[m_trackeRegion.currentCount].left = pTracker->curRect.x;
  471. m_trackeRegion.rect[m_trackeRegion.currentCount].top = pTracker->curRect.y;
  472. m_trackeRegion.rect[m_trackeRegion.currentCount].right = pTracker->curRect.x + pTracker->curRect.width;
  473. m_trackeRegion.rect[m_trackeRegion.currentCount].bottom = pTracker->curRect.y + pTracker->curRect.height;
  474. m_trackeRegion.currentCount++;
  475. m_RegionCount++;
  476. pTracker->bStatOK = true;
  477. }
  478. }
  479. }

效果展示:

跟踪的原理:

用yolo-tiny检测出来的结果,送到KCF跟踪 器中,连续匹配上两次,则确认为一个目标,之后采用tracking-by-detection的方式进行人头跟踪。

人头跟踪的demo(内涵KCF跟踪代码部分):

链接:百度网盘 请输入提取码
提取码:dr2a

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
风清扬
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区