VerificationTools.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. #include "VerificationTools.h"
  2. #include <opencv2/opencv.hpp>
  3. #include "VerificationTools.h"
  4. #include <opencv2/opencv.hpp>
  5. #include<opencv2/video.hpp>
  6. #include <opencv2/highgui/highgui_c.h>
  7. using namespace std;
  8. using namespace cv;
  9. void test()
  10. {
  11. int ptsNum = 200;
  12. //vector<Point> roiLesion(ptsNum);
  13. //cv::imread("");
  14. }
  15. bool JudgeRoi(Rect& roi, int srcW, int srcH)
  16. {
  17. if (roi.x < 0)
  18. {
  19. roi.x = 0;
  20. }
  21. if (roi.y < 0)
  22. {
  23. roi.y = 0;
  24. }
  25. if ((roi.x + roi.width >= srcW - 1))
  26. {
  27. roi.width = srcW - 1 - roi.x;
  28. }
  29. if (roi.y + roi.height >= srcH - 1)
  30. {
  31. roi.height = srcH - 1 - roi.y;
  32. }
  33. return true;
  34. }
  35. void __cdecl BreastDescriptionLesionsRect(int imgW, int imgH, MyPoint* contourPts, int contourLen, RoiCoor lesionRectPr, int& sameLesion)
  36. {
  37. try
  38. {
  39. Mat lesionImagePr = Mat::zeros(imgH, imgW, CV_8UC1);
  40. Point pt1[4], pt2;
  41. Point rookPoints[1][4];
  42. rookPoints[0][0].x = lesionRectPr.x;
  43. rookPoints[0][0].y = lesionRectPr.y;
  44. rookPoints[0][1].x = lesionRectPr.x + lesionRectPr.width;
  45. rookPoints[0][1].y = lesionRectPr.y;
  46. rookPoints[0][2].x = lesionRectPr.x + lesionRectPr.width;
  47. rookPoints[0][2].y = lesionRectPr.y + lesionRectPr.height;
  48. rookPoints[0][3].x = lesionRectPr.x;
  49. rookPoints[0][3].y = lesionRectPr.y + lesionRectPr.height;
  50. const Point* ppt[1] = { rookPoints[0] };
  51. int npt[] = { 4 };
  52. cv::fillPoly(lesionImagePr, ppt,npt, 1, 50);
  53. int contLen = contourLen;
  54. vector<Point> contour = vector<Point>(contLen);
  55. vector<vector<Point>> contours;
  56. MyPoint p;
  57. Point pt;
  58. for (int ni = 0; ni < contLen; ni++)
  59. {
  60. p = contourPts[ni];
  61. pt = Point(p.x, p.y);
  62. contour[ni] = pt;
  63. }
  64. contours.push_back(contour);
  65. //cv::drawContours(lesionImage, contours, 0, Scalar(51), -1, LINE_8);//CV_FILLED或者负值表示填充,正值代表宽度
  66. Mat lesionImageGt = Mat::zeros(imgH, imgW, CV_8UC1);
  67. Rect lesionROI = cv::boundingRect(contour);
  68. cv::rectangle(lesionImageGt, lesionROI, 50, -1); //轮廓的外接矩形
  69. /*lesionRect.x = lesionROI.x;
  70. lesionRect.y = lesionROI.y;
  71. lesionRect.width = lesionROI.width;
  72. lesionRect.height = lesionROI.height;*/
  73. Mat dst = lesionImageGt + lesionImagePr;
  74. int areaNum = countNonZero(dst);
  75. threshold(dst, dst, 51,255, THRESH_BINARY);
  76. int repeatNum = countNonZero(dst);
  77. float ratio = 0;
  78. if (areaNum > 0)
  79. {
  80. ratio = (float)repeatNum / (float)areaNum;
  81. }
  82. if (ratio > 0.25)
  83. {
  84. sameLesion = 1;
  85. }
  86. }
  87. catch (...)
  88. {
  89. return;
  90. }
  91. }
  92. void __cdecl DescriptionLesionsRect(int imgW, int imgH, MyPoint* contourPts, int contourLen, RoiCoor& lesionRectPr)
  93. {
  94. try
  95. {
  96. Mat lesionImage = Mat::zeros(imgH, imgW, CV_8UC1);
  97. int contLen = contourLen;
  98. vector<Point> contour = vector<Point>(contLen);
  99. vector<vector<Point>> contours;
  100. MyPoint p;
  101. Point pt;
  102. for (int ni = 0; ni < contLen; ni++)
  103. {
  104. p = contourPts[ni];
  105. pt = Point(p.x, p.y);
  106. contour[ni] = pt;
  107. }
  108. contours.push_back(contour);
  109. //cv::drawContours(lesionImage, contours, 0, Scalar(51), -1, LINE_8);//CV_FILLED或者负值表示填充,正值代表宽度
  110. Rect lesionROI = cv::boundingRect(contour);
  111. lesionROI.x = lesionROI.x - 10;
  112. lesionROI.y = lesionROI.y - 10;
  113. lesionROI.width = lesionROI.width + 20;
  114. lesionROI.height = lesionROI.height + 20;
  115. JudgeRoi(lesionROI, imgW, imgH);
  116. lesionRectPr.x = lesionROI.x - 10;
  117. lesionRectPr.y = lesionROI.y - 10;
  118. lesionRectPr.width = lesionROI.width + 20;
  119. lesionRectPr.height = lesionROI.height + 20;
  120. }
  121. catch (...)
  122. {
  123. return;
  124. }
  125. }
  126. //用于胆囊壁标注数据,
  127. void __cdecl GallGetContours(char* name, int nameLen, __inout MyPoint* contour_points_out, __inout MyPoint* contour_points_in, __inout int* contourLen)
  128. {
  129. //FILE* fp;
  130. //fp = fopen("e:\\image\\nameGall.csv", "a+"); //设置保存文件
  131. //fprintf(fp, "%s,%d,\n", name, 1);//写入
  132. //fclose(fp);
  133. //sprintf(name, "D:\\imaged\\vediostatic\\43.0_%d.jpg", k);
  134. string imgId = name;
  135. string pathOut = "E:\\image\\胆囊\\标注\\data3\\maskout\\" + imgId + ".jpg"; //外轮廓mask
  136. string pathIn = "E:\\image\\胆囊\\标注\\data3\\maskin\\" + imgId + ".jpg"; //内轮廓mask
  137. Mat out = cv::imread(pathOut,0);
  138. Mat in = cv::imread(pathIn,0);
  139. /*if (out.empty() || in.empty())
  140. {
  141. contourLen[0] = 0;
  142. contourLen[1] = 0;
  143. return;
  144. }*/
  145. if (!out.empty())
  146. {
  147. vector<vector<Point>> outPts;
  148. cv::findContours(out, outPts, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  149. int outNum = outPts[0].size();
  150. for (int i = 0;i < outNum; i++)
  151. {
  152. contour_points_out[i].x = outPts[0][i].x;
  153. contour_points_out[i].y = outPts[0][i].y;
  154. }
  155. contourLen[0] = outPts[0].size();
  156. }
  157. if (!in.empty())
  158. {
  159. vector<vector<Point>> inPts;
  160. cv::findContours(in, inPts, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  161. int inNum = inPts[0].size();
  162. for (int i = 0;i < inNum; i++)
  163. {
  164. contour_points_in[i].x = inPts[0][i].x;
  165. contour_points_in[i].y = inPts[0][i].y;
  166. }
  167. contourLen[1] = inPts[0].size();
  168. }
  169. }
  170. //处理数据,生成模型需要的输入
  171. //当前模型需要四通道数据,前三通道为bgr原图,最后一个通道为将病灶挖出的图
  172. //modelW,modelH,modelChannel模型需要的输入尺寸
  173. //RoiCoor:从原图上截取的roi坐标
  174. void __cdecl ThyroidDescriptionModelProcess(__in unsigned char* imgData, int channel, int imgW, int imgH,
  175. RoiCoor roiVec, int ptsNum1, MyPoint* thyroidPts, int ptsNum2, MyPoint* lesionPts,
  176. int modelW, int modelH, int modelChannel, RoiCoor& roiDst, __out unsigned char* imgDataDst)
  177. {
  178. try
  179. {
  180. if (imgData == NULL)
  181. {
  182. return;
  183. }
  184. if (!(channel == 1 || channel == 3 || channel == 4))
  185. {
  186. return;
  187. }
  188. Mat srcImg(cv::Size(imgW, imgH), CV_8UC(channel), imgData);
  189. Mat grayImg(srcImg.size(), srcImg.depth());
  190. if (channel > 1)
  191. {
  192. cv::cvtColor(srcImg, grayImg, COLOR_BGR2GRAY);
  193. }
  194. else
  195. {
  196. grayImg = srcImg.clone();
  197. }
  198. cv::Rect roi;
  199. bool existRoi = false;
  200. if (existRoi == true)
  201. {
  202. roi.x = roiVec.x;
  203. roi.y = roiVec.y;
  204. roi.width = roiVec.width;
  205. roi.height = roiVec.height;
  206. }
  207. else
  208. {
  209. vector<Point> lesionContTemp(ptsNum2);
  210. for (int i = 0; i < ptsNum2; i++)
  211. {
  212. lesionContTemp[i].x = lesionPts[i].x;
  213. lesionContTemp[i].y = lesionPts[i].y;
  214. }
  215. roi = cv::boundingRect(lesionContTemp);
  216. //部分数据在标注时存在偏差,可能会出现钙化超出病灶的情况,适当扩大ROI区域
  217. roi.x -= 10;
  218. roi.y -= 10;
  219. roi.width += 20;
  220. roi.height += 20;
  221. }
  222. JudgeRoi(roi, imgW, imgH);
  223. roiDst.x = roi.x;
  224. roiDst.y = roi.y;
  225. roiDst.width = roi.width;
  226. roiDst.height = roi.height;
  227. Mat roiImg = grayImg(roi);
  228. Mat roiImgSrc = srcImg(roi);
  229. //vector<Point> thyroidCont(ptsNum1);
  230. vector<Point> thyroidCont;
  231. Point pt;
  232. for (int i = 0; i < ptsNum1; i++)
  233. {
  234. if (thyroidPts[i].x < 0)
  235. {
  236. thyroidPts[i].x = 0;
  237. }
  238. else if (thyroidPts[i].x >= imgW)
  239. {
  240. thyroidPts[i].x = imgW - 1;
  241. }
  242. if (thyroidPts[i].y < 0)
  243. {
  244. thyroidPts[i].y = 0;
  245. }
  246. else if (thyroidPts[i].y >= imgH)
  247. {
  248. thyroidPts[i].y = imgH - 1;
  249. }
  250. pt.x = thyroidPts[i].x;
  251. pt.y = thyroidPts[i].y;
  252. thyroidCont.push_back(pt);
  253. }
  254. ptsNum1 = thyroidCont.size();
  255. vector<Point> lesionCont(ptsNum2);
  256. vector<Point> lesionContSrc(ptsNum2);
  257. for (int i = 0; i < ptsNum2; i++)
  258. {
  259. lesionCont[i].x = lesionPts[i].x - roi.x;
  260. lesionCont[i].y = lesionPts[i].y - roi.y;
  261. lesionContSrc[i].x = lesionPts[i].x;
  262. lesionContSrc[i].y = lesionPts[i].y;
  263. }
  264. Mat cropLesionMask = Mat::zeros(cv::Size(roi.width, roi.height), CV_8UC1);
  265. vector<vector<Point>> contours;
  266. contours.push_back(lesionCont);
  267. cv::drawContours(cropLesionMask, contours, 0, Scalar(255), FILLED, LINE_8);//CV_FILLED或者负值表示填充,正值代表宽度
  268. Mat cropLesionImg;
  269. cv::bitwise_and(roiImg, cropLesionMask, cropLesionImg);
  270. #ifdef _DEBUG
  271. //Mat showSrcImg(cv::Size(imgW, imgH), CV_8UC(3), imgData);
  272. Mat showSrcImg = srcImg.clone();
  273. if (showSrcImg.channels() < 3)
  274. {
  275. cv::cvtColor(showSrcImg, showSrcImg, COLOR_GRAY2BGR);
  276. }
  277. for (int i = 0; i < ptsNum1; i++)
  278. {
  279. showSrcImg.at<Vec3b>(thyroidCont[i].y, thyroidCont[i].x) = Vec3b(0, 255, 0);
  280. }
  281. #endif
  282. Mat modelImage;
  283. if (modelChannel == 4)
  284. {
  285. modelImage = Mat(cv::Size(imgW, imgH), CV_8UC4);
  286. modelImage = Mat(cv::Size(imgW, imgH), CV_8UC4);
  287. Mat dstSingle[4];
  288. if (channel == 1)
  289. {
  290. dstSingle[0] = roiImgSrc;
  291. dstSingle[1] = roiImgSrc;
  292. dstSingle[2] = roiImgSrc;
  293. dstSingle[3] = cropLesionImg;
  294. }
  295. else if (channel == 3)
  296. {
  297. Mat single[3];
  298. cv::split(roiImgSrc, single);
  299. dstSingle[0] = single[0];
  300. dstSingle[1] = single[1];
  301. dstSingle[2] = single[2];
  302. dstSingle[3] = cropLesionImg;
  303. }
  304. else if (channel == 4)
  305. {
  306. Mat single[4];
  307. cv::split(roiImgSrc, single);
  308. dstSingle[0] = single[0];
  309. dstSingle[1] = single[1];
  310. dstSingle[2] = single[2];
  311. dstSingle[3] = cropLesionImg;
  312. }
  313. cv::merge(dstSingle, 4, modelImage);
  314. Mat dst;
  315. cv::resize(modelImage, dst, cv::Size(modelW, modelH), INTER_NEAREST);//在此处进行resize
  316. //imgDataDst = modelImage.data;
  317. memcpy(imgDataDst, dst.data, sizeof(char) * modelW * modelH * modelChannel);
  318. }
  319. }
  320. catch (...)
  321. {
  322. return;
  323. }
  324. }
  325. //处理钙化模型得到的钙化数据,求出每个钙化区域的轮廓点
  326. void __cdecl ThyroidDescriptionModelProcessModelImage(__in unsigned char* imgModelData, int imgModelW, int imgModelH, int channelModel,
  327. RoiCoor roiModelVec, int& contourNum, int* contourLen, __inout MyPoint* calcificationPts)
  328. {
  329. int size = imgModelW * imgModelH;
  330. char* data = new char[size];
  331. for (int nj = 0; nj < size; nj++)//第一通道为背景
  332. {
  333. data[nj] = imgModelData[size + nj];
  334. }
  335. Mat srcImgModel(cv::Size(imgModelW, imgModelH), CV_8UC1, data);
  336. Mat dst;
  337. int lesionW = roiModelVec.width;
  338. int lesionH = roiModelVec.height;
  339. cv::resize(srcImgModel, dst, cv::Size(lesionW, lesionH), INTER_NEAREST);//在此处进行resize
  340. vector<vector<Point>> contours; //钙化区域的区域轮廓
  341. cv::findContours(dst, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  342. int calNum = contours.size();
  343. contourNum = calNum;
  344. Point pt = Point(0, 0);
  345. int startInd = 0;
  346. for (int i = 0; i < calNum; i++)
  347. {
  348. vector<Point> contour = contours[i];
  349. int len = contour.size();
  350. for (int j = 0; j < len; j++)
  351. {
  352. pt = contour[j];
  353. calcificationPts[startInd + j].x = pt.x + roiModelVec.x;
  354. calcificationPts[startInd + j].y = pt.y + roiModelVec.y;
  355. }
  356. contourLen[i] = len;
  357. startInd += len;
  358. }
  359. //释放内存
  360. delete[] data;
  361. }
  362. //
  363. void __cdecl ThyroidDescriptionContour(__in unsigned char* imgData, int channel, int imgW, int imgH,
  364. RoiCoor roiVec, int ptsNum1, MyPoint* lesionPts, RoiCoor& roiDst)
  365. {
  366. if (imgData == NULL)
  367. {
  368. return;
  369. }
  370. if (!(channel == 1 || channel == 3 || channel == 4))
  371. {
  372. return;
  373. }
  374. Mat srcImg(cv::Size(imgW, imgH), CV_8UC(channel), imgData);
  375. Mat grayImg(srcImg.size(), srcImg.depth());
  376. if (channel > 1)
  377. {
  378. cv::cvtColor(srcImg, grayImg, COLOR_BGR2GRAY);
  379. }
  380. else
  381. {
  382. grayImg = srcImg.clone();
  383. }
  384. cv::Rect roi;
  385. bool existRoi = false;
  386. if (existRoi == true)
  387. {
  388. roi.x = roiVec.x;
  389. roi.y = roiVec.y;
  390. roi.width = roiVec.width;
  391. roi.height = roiVec.height;
  392. }
  393. else
  394. {
  395. vector<Point> lesionContTemp(ptsNum1);
  396. for (int i = 0; i < ptsNum1; i++)
  397. {
  398. lesionContTemp[i].x = lesionPts[i].x;
  399. lesionContTemp[i].y = lesionPts[i].y;
  400. }
  401. roi = cv::boundingRect(lesionContTemp);
  402. roi.x -= 10;
  403. roi.y -= 10;
  404. roi.width += 20;
  405. roi.height += 20;
  406. }
  407. JudgeRoi(roi, imgW, imgH);
  408. //Mat roiImg = grayImg(roi);
  409. //Point pt;
  410. //vector<Point> lesionCont(ptsNum1);
  411. //vector<Point> lesionContSrc(ptsNum1);
  412. //for (int i = 0; i < ptsNum1; i++)
  413. //{
  414. // lesionCont[i].x = lesionPts[i].x - roi.x;
  415. // lesionCont[i].y = lesionPts[i].y - roi.y;
  416. // lesionContSrc[i].x = lesionPts[i].x;
  417. // lesionContSrc[i].y = lesionPts[i].y;
  418. //}
  419. //Mat lesionMask = Mat::zeros(roi.height, roi.width, CV_8UC1);
  420. //vector<vector<Point>> contours;
  421. //contours.push_back(lesionCont);
  422. //cv::drawContours(lesionMask, contours, 0, Scalar(255), FILLED, LINE_8);//CV_FILLED或者负值表示填充,正值代表宽度
  423. //vector<vector<Point> > contour_vec;
  424. //vector<Vec4i> hierarchy;
  425. //findContours(lesionMask, contour_vec, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  426. //Rect boundRect;
  427. //boundRect = boundingRect(Mat(contour_vec[0]));
  428. ////Mat imageContoursrect = Mat::zeros(lesionMask.size(), CV_8UC1); //最小外接正矩形画布
  429. ////rectangle(imageContoursrect, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar(255), 2, 8);
  430. ////Rect rect = minAreaRect(contour_vec[0]);
  431. //roiDst.x = boundRect.x + roi.x;
  432. //roiDst.y = boundRect.y + roi.y;
  433. //roiDst.width = boundRect.width;
  434. //roiDst.height = boundRect.height;
  435. roiDst.x = roi.x;
  436. roiDst.y = roi.y;
  437. roiDst.width = roi.width;
  438. roiDst.height = roi.height;
  439. }
  440. void __cdecl video2image()
  441. {
  442. VideoCapture capture("E:\\image\\颈动脉\\hor1.mp4");
  443. if (!capture.isOpened())
  444. {
  445. return;
  446. }
  447. int frameH = capture.get(CAP_PROP_FRAME_HEIGHT);
  448. int frameW = capture.get(CAP_PROP_FRAME_WIDTH);
  449. int fps = capture.get(CAP_PROP_FPS);
  450. long numFrames = capture.get(CAP_PROP_FRAME_COUNT);
  451. //printf("vedio's width = %d\t height = %d\nvideo's fps = %d\t nums = %d", frameW, frameH, fps, numFrames);
  452. int imgIndex = 1;
  453. while (1)
  454. {
  455. //std::cout << "第" << imgIndex << "幅图像" << std::endl;
  456. Mat frame;
  457. capture >> frame;
  458. if (frame.empty())
  459. {
  460. break;
  461. }
  462. //char* imageSaveName = new char[200];
  463. char imageSaveName[512];
  464. //将图片的路径及名称输入到imageSaveName中
  465. //string path = "D:\\imaged\\甲状腺\\20221213\\2022-11-29\\[zhangya--2-甲y]-[20221123003]-[55df3ec4-5d38-4e37-aff3-f5cd0083b761]\\3\\1129_10_3_" + to_string(imgIndex) + ".png";
  466. sprintf_s(imageSaveName, "E:\\image\\颈动脉\\hor1\\230914%05d.jpg", imgIndex);
  467. //将每一帧图像frame保存到imageSaveName指定的文件中
  468. imwrite(imageSaveName, frame);
  469. //delete[] imageSaveName;_
  470. imgIndex++;
  471. /*if (waitKey(20) > 0)
  472. {
  473. break;
  474. }*/
  475. if (imgIndex > 4000)
  476. {
  477. break;
  478. }
  479. }
  480. capture.release();
  481. //cout << "total frames: " << imgIndex << endl;
  482. }
  483. void __cdecl Image_to_video_2()
  484. {
  485. char filename[100];
  486. VideoWriter writer;
  487. int codec = writer.fourcc('X', 'V', 'I', 'D');
  488. VideoWriter video("D:\\imaged\\甲状腺\\视频\\img.mp4", codec,
  489. 10.0, Size(596, 650), true);
  490. String img_path = "D:\\imaged\\甲状腺\\视频\\img\\*.jpg";
  491. vector<String> imgname;
  492. glob(img_path, imgname, false); //glob:获取文件路径下的所有图片
  493. size_t count = imgname.size();
  494. for (size_t i = 0; i < count; i++)
  495. //for (int i = 1; i <= 10; i++)
  496. {
  497. sprintf(filename, "D:\\imaged\\甲状腺\\视频\\img\\230801%05d.jpg", i);
  498. string ss = imgname[i].c_str();
  499. Mat image = imread(ss);
  500. //resize(image, image, Size(1920, 1080));
  501. video << image;
  502. }
  503. }
  504. //用于胆囊病灶标注数据,
  505. void __cdecl GallLesionGetContours(char* name, int nameLen, __inout MyPoint* contour_points, __inout int* contourLen, int& GallLesionNum)
  506. {
  507. //FILE* fp;
  508. //fp = fopen("e:\\image\\nameGall.csv", "a+"); //设置保存文件
  509. //fprintf(fp, "%s,%d,\n", name, 1);//写入
  510. //fclose(fp);
  511. //sprintf(name, "D:\\imaged\\vediostatic\\43.0_%d.jpg", k);
  512. string imgId = name;
  513. string path = "F:\\image\\胆囊疾病\\gall2\\mask\\" /*+ imgId + ".jpg"*/; //外轮廓mask
  514. //string pathIn = "E:\\image\\胆囊\\标注\\data4\\maskin\\" + imgId + ".jpg"; //内轮廓mask
  515. vector<string> imgName;
  516. int lesionNum = 0;
  517. int ptsNum = 0;
  518. for (int i = 0; i < 10;i++)
  519. {
  520. string ss = to_string(i);
  521. string name = path + imgId + "_" + ss + ".jpg";
  522. Mat img = cv::imread(name, 0);
  523. if (!img.empty())
  524. {
  525. vector<vector<Point>> outPts;
  526. cv::findContours(img, outPts, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  527. int outNum = outPts[0].size();
  528. for (int j = 0;j < outNum; j++)
  529. {
  530. contour_points[ptsNum + j].x = outPts[0][j].x;
  531. contour_points[ptsNum + j].y = outPts[0][j].y;
  532. }
  533. ptsNum = ptsNum + outNum;
  534. contourLen[i] = outPts[0].size();
  535. lesionNum++;
  536. }
  537. }
  538. GallLesionNum = lesionNum;
  539. }