Class1.cs 142 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using OpenCvSharp;
  7. using System.Collections;
  8. namespace ceju
  9. {
  10. class Classification
  11. {
  12. public static void Qianmangkong(string fileName)
  13. { //获取图片
  14. Mat image = new Mat(fileName, ImreadModes.Color);
  15. //获取图片的长宽
  16. int rows = image.Rows;
  17. int cols = image.Cols;
  18. //将图片转换为灰度图片
  19. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  20. //获取图片的通道数
  21. int channels = image.Channels();
  22. //获得蓝色,绿色,红色通道图片
  23. Mat imageBlue,imageGreen,imageRed = new Mat(imageGray.Size(), imageGray.Type());
  24. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  25. double proportion = 0.2689;
  26. /*
  27. * 一、
  28. * 1、对图像进行阈值分割,选取目标区域,阈值选取用Otsu方法
  29. * 2、对于一些小的孔洞进行填充(没实现,待定)
  30. * 3、进行sobel算子的边缘检测,横纵向边缘的平均
  31. * 4、去掉小面积(没实现,待定)
  32. *
  33. */
  34. //Otsu阈值分割
  35. Mat imageThresh = imageRed.Threshold(0, 255, ThresholdTypes.Otsu);//最大值调成1的话显示不出来,在转换成数组的时候注意255要变成1
  36. //sobel算子边缘检测
  37. //横向检测
  38. Mat grad_x = new Mat();
  39. Mat grad_x2 = new Mat();
  40. Cv2.Sobel(imageThresh, grad_x, MatType.CV_16S, 1, 0);
  41. Cv2.ConvertScaleAbs(grad_x, grad_x2);
  42. //纵向检测
  43. Mat grad_y = new Mat();
  44. Mat grad_y2 = new Mat();
  45. Cv2.Sobel(imageThresh, grad_y, MatType.CV_16S, 0, 1);
  46. Cv2.ConvertScaleAbs(grad_y, grad_y2);
  47. //横纵向混合平均
  48. Mat imageSobel = new Mat();
  49. Cv2.AddWeighted(grad_x2, 0.5, grad_y2, 0.5, 0, imageSobel);
  50. //将imageThresh的Mat类转换成数组,并且是0,1二值
  51. //将Mat类中的数组转为数组
  52. int[,] arrayThresh = BasFunction.Mat2Array(imageThresh);
  53. //将数组转为0,1数组
  54. arrayThresh = BasFunction.ConversionRange(arrayThresh);
  55. //将sobel边缘检测后的轮廓线转为0,1二值
  56. int[,] arraySobel = BasFunction.Mat2Array(imageSobel);
  57. arraySobel = BasFunction.ConversionRange(arraySobel);
  58. // 二、计算中部区域的边界,middleArea[0]中部左边界,middleArea[1]中部右边界
  59. int[] middleArea = SubFunction.GetMiddleArea(imageThresh);
  60. //显示线条
  61. //SubFunction.LineShow(image, middleArea[0], 0, middleArea[0], rows,"red");
  62. //SubFunction.LineShow(image, middleArea[1], 0, middleArea[1], rows,"green");
  63. //new Window("middleArea", WindowMode.Normal, image);
  64. //Cv2.WaitKey(0);
  65. // 三、计算数据提取区域的边界
  66. //dataArea[0]左部分左边界,dataArea[1]左部分右边界,dataArea[2]右部分左边界,dataArea[3]右部分右边界
  67. int[] dataArea = SubFunction.GetDataArea(imageThresh,middleArea);
  68. //叠加线条
  69. //SubFunction.LineShow(image, dataArea[0], 0, dataArea[0], rows,"red");
  70. //SubFunction.LineShow(image, dataArea[1], 0, dataArea[1], rows,"green");
  71. //SubFunction.LineShow(image, dataArea[2], 0, dataArea[2], rows,"blue");
  72. //SubFunction.LineShow(image, dataArea[3], 0, dataArea[3], rows,"red");
  73. //new Window("middleArea", WindowMode.Normal, image);
  74. //Cv2.WaitKey(0);
  75. // 四、提取L1、L3、L4、L5
  76. //腐蚀结构[1,1,1];
  77. Mat seErode = Cv2.GetStructuringElement(MorphShapes.Rect,new Size(3,1));
  78. //腐蚀
  79. Mat outLine = new Mat();//轮廓线
  80. Cv2.Erode(imageSobel, outLine, seErode);
  81. //将轮廓线的腐蚀后转为0,1二值
  82. int[,] arrayOutline = BasFunction.Mat2Array(outLine);
  83. arrayOutline = BasFunction.ConversionRange(arrayOutline);
  84. //提取线条
  85. //线条L1数组
  86. int[,] line1 = new int[rows, cols];
  87. //L1的纵坐标
  88. double averageCoordinate1 = 0;
  89. //得到L1,以及L1的平均纵坐标。
  90. SubFunction.ExtractLines(arraySobel,out line1,out averageCoordinate1, dataArea[0], dataArea[3]);
  91. //得到L1左部分,以及平均纵坐标
  92. int[,] lineLeft1 = new int[rows, cols];
  93. double meanOrdinateLeft1 = 0;
  94. SubFunction.ExtractLines(arraySobel, out lineLeft1, out meanOrdinateLeft1, dataArea[0], dataArea[1]);
  95. //得到L3左部分,以及平均纵坐标
  96. int[,] lineLeft3 = new int[rows, cols];
  97. double meanOrdinateLeft3 = 0;
  98. SubFunction.ExtractLines(arraySobel,out lineLeft3, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1);
  99. //得到L4左部分,以及平均纵坐标
  100. int[,] lineLeft4 = new int[rows, cols];
  101. double meanOrdinateLeft4 = 0;
  102. SubFunction.ExtractLines(arrayOutline, out lineLeft4, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3);
  103. //得到L5左部分,以及平均纵坐标
  104. int[,] lineLeft5 = new int[rows, cols];
  105. double meanOrdinateLeft5 = 0;
  106. SubFunction.ExtractLines(arrayOutline, out lineLeft5, out meanOrdinateLeft5, dataArea[0], dataArea[1], meanOrdinateLeft4);
  107. //得到L1右部分,以及平均纵坐标
  108. int[,] lineRight1 = new int[rows, cols];
  109. double meanOrdinateRight1 = 0;
  110. SubFunction.ExtractLines(arraySobel, out lineRight1, out meanOrdinateRight1, dataArea[2], dataArea[3]);
  111. //得到L3右部分,以及平均纵坐标
  112. int[,] lineRight3 = new int[rows, cols];
  113. double meanOrdinateRight3 = 0;
  114. SubFunction.ExtractLines(arraySobel, out lineRight3, out meanOrdinateRight3, dataArea[2], dataArea[3], meanOrdinateRight1);
  115. //得到L4右部分,以及平均纵坐标
  116. int[,] lineRight4 = new int[rows, cols];
  117. double meanOrdinateRight4 = 0;
  118. SubFunction.ExtractLines(arrayOutline, out lineRight4, out meanOrdinateRight4, dataArea[2], dataArea[3], meanOrdinateRight3);
  119. //得到L5右部分,以及平均纵坐标
  120. int[,] lineRight5 = new int[rows, cols];
  121. double meanOrdinateRight5 = 0;
  122. SubFunction.ExtractLines(arrayOutline, out lineRight5, out meanOrdinateRight5, dataArea[2], dataArea[3], meanOrdinateRight4);
  123. //显示线条重叠
  124. SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft1, dataArea[1], (int)meanOrdinateLeft1);
  125. SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft3, dataArea[1], (int)meanOrdinateLeft3);
  126. SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft4, dataArea[1], (int)meanOrdinateLeft4);
  127. SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft5, dataArea[1], (int)meanOrdinateLeft5);
  128. SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight1, dataArea[3], (int)meanOrdinateRight1);
  129. SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight3, dataArea[3], (int)meanOrdinateRight3);
  130. SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight4, dataArea[3], (int)meanOrdinateRight4);
  131. SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight5, dataArea[3], (int)meanOrdinateRight5);
  132. //new Window("middleArea", WindowMode.Normal, image);
  133. //Cv2.WaitKey(0);
  134. //五、求L2
  135. double meanOrdinateLeft2 = 0;
  136. double meanOrdinateRight2 = 0;
  137. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2);
  138. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea[2], dataArea[3], out meanOrdinateRight2);
  139. //七、孔铜
  140. //得到孔径起止点
  141. //aperture[0]孔径起始点(左);aperture[1]孔径起始点(右)
  142. int[] aperture = new int[2];
  143. SubFunction.GetAperture(arrayThresh,out aperture, (int)meanOrdinateLeft3, (int)meanOrdinateRight3, middleArea, dataArea);
  144. int[] apertureBegin = { (int)meanOrdinateLeft3, aperture[0] };
  145. int[] apertureEnd = { (int)meanOrdinateRight3, aperture[1] };
  146. //孔径中点
  147. double middleAperture = (aperture[0] + aperture[1]) / 2;
  148. //求孔径起始点与曲面之间的最短距离,以及最短距离时的曲面坐标
  149. double[] kongtong = new double[2];
  150. int[] pointLeft = new int[2];
  151. int[] pointRight = new int[2];
  152. SubFunction.GetKongtong(line1, apertureBegin, apertureEnd, out kongtong,out pointLeft,out pointRight);
  153. //九、下孔径
  154. int[] apertureLow = new int[2];
  155. SubFunction.GetAperture(arrayThresh, out apertureLow, (int)meanOrdinateLeft4, (int)meanOrdinateRight4, middleArea, dataArea);
  156. //十、孔底与孔深
  157. //提取曲面最凸点坐标
  158. int[] curveVertex = new int[2];
  159. //孔径平均高度
  160. double middleApertureY;
  161. SubFunction.CurveVertex(line1, apertureBegin, apertureEnd, out curveVertex,out middleApertureY);
  162. //六、求L6
  163. double t1 = 0;
  164. double t2 = 0;
  165. double meanOrdinateL6 = 0;
  166. BasFunction.ChooseSize(meanOrdinateLeft4, meanOrdinateRight4, "small", out t1);
  167. BasFunction.ChooseSize(meanOrdinateLeft5, meanOrdinateRight5, "small", out t2);
  168. SubFunction.InsideLine(imageGreen, (int)t1 - 10, (int)meanOrdinateLeft5-10, (int)middleAperture - 90, (int)middleAperture + 90,out meanOrdinateL6);
  169. //int[,] arrayIrg = new int[rows, cols];
  170. // 十一、数据计算
  171. double leftMiantong = meanOrdinateLeft2 - meanOrdinateLeft1;
  172. double rightMiantong = meanOrdinateRight2 - meanOrdinateRight1;
  173. double leftJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2;
  174. double rightJicaitong = meanOrdinateRight3 - meanOrdinateRight2;
  175. double leftMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1;
  176. double rightMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1;
  177. double shangKongjing = aperture[1] - aperture[0];
  178. double xiaKongjing = apertureLow[1] - aperture[0];
  179. double leftKongtong = kongtong[0];
  180. double rightKongtong = kongtong[1];
  181. double averAperture = (apertureBegin[0] + apertureEnd[1]) / 2;
  182. //double kongshen = curveVertex[0]-middleApertureY;
  183. double kongdi = meanOrdinateL6 - curveVertex[0];
  184. double leftKongdiyaoshiliang = meanOrdinateL6 - meanOrdinateLeft4;
  185. double rightKongdiyaoshiliang = meanOrdinateL6 - meanOrdinateRight4;
  186. // 十二、数据显示
  187. double middleLeft = (dataArea[0] + dataArea[1]) / 2;
  188. double middleRight = (dataArea[2] + dataArea[3]) / 2;
  189. //左面铜标注
  190. SubFunction.LineShow(image, (int)middleLeft - 20, (int)meanOrdinateLeft1, (int)middleLeft - 20, (int)meanOrdinateLeft2, "blue");
  191. SubFunction.LineShow(image, (int)middleLeft - 25, (int)meanOrdinateLeft1, (int)middleLeft - 15, (int)meanOrdinateLeft1, "blue");
  192. SubFunction.LineShow(image, (int)middleLeft - 25, (int)meanOrdinateLeft2, (int)middleLeft - 15, (int)meanOrdinateLeft2, "blue");
  193. SubFunction.TextShow(image, leftMiantong * proportion, (int)middleLeft - 20, (int)meanOrdinateLeft2);
  194. //右面铜标注
  195. SubFunction.LineShow(image, (int)middleRight + 20, (int)meanOrdinateRight1, (int)middleRight + 20, (int)meanOrdinateRight2, "blue");
  196. SubFunction.LineShow(image, (int)middleRight + 15, (int)meanOrdinateRight1, (int)middleRight + 25, (int)meanOrdinateRight1, "blue");
  197. SubFunction.LineShow(image, (int)middleRight + 15, (int)meanOrdinateRight2, (int)middleRight + 25, (int)meanOrdinateRight2, "blue");
  198. SubFunction.TextShow(image, rightMiantong * proportion, (int)middleRight + 20, (int)meanOrdinateRight2);
  199. //左基材铜标注
  200. SubFunction.LineShow(image, (int)middleLeft - 40, (int)meanOrdinateLeft2, (int)middleLeft - 40, (int)meanOrdinateLeft3, "blue");
  201. SubFunction.LineShow(image, (int)middleLeft - 45, (int)meanOrdinateLeft2, (int)middleLeft - 35, (int)meanOrdinateLeft2, "blue");
  202. SubFunction.LineShow(image, (int)middleLeft - 45, (int)meanOrdinateLeft3, (int)middleLeft - 35, (int)meanOrdinateLeft3, "blue");
  203. SubFunction.TextShow(image, leftJicaitong * proportion, (int)middleLeft - 40, (int)meanOrdinateLeft3);
  204. //右基材铜标注
  205. SubFunction.LineShow(image, (int)middleRight + 40, (int)meanOrdinateRight2, (int)middleRight + 40, (int)meanOrdinateRight3, "blue");
  206. SubFunction.LineShow(image, (int)middleRight + 35, (int)meanOrdinateRight2, (int)middleRight + 45, (int)meanOrdinateRight2, "blue");
  207. SubFunction.LineShow(image, (int)middleRight + 35, (int)meanOrdinateRight3, (int)middleRight + 45, (int)meanOrdinateRight3, "blue");
  208. SubFunction.TextShow(image, rightJicaitong * proportion, (int)middleRight + 40, (int)meanOrdinateRight3);
  209. //左面铜+基材铜标注
  210. SubFunction.LineShow(image, (int)middleLeft, (int)meanOrdinateLeft1, (int)middleLeft, (int)meanOrdinateLeft3, "blue");
  211. SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateLeft1, (int)middleLeft + 5, (int)meanOrdinateLeft1, "blue");
  212. SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateLeft3, (int)middleLeft + 5, (int)meanOrdinateLeft3, "blue");
  213. SubFunction.TextShow(image, leftMian_Jicaitong*0.2689, (int)middleLeft, (int)meanOrdinateLeft3+50);
  214. //右面铜+基材铜标注
  215. SubFunction.LineShow(image, (int)middleRight, (int)meanOrdinateRight1, (int)middleRight, (int)meanOrdinateRight3, "blue");
  216. SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateRight1, (int)middleRight + 5, (int)meanOrdinateRight1, "blue");
  217. SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateRight3, (int)middleRight + 5, (int)meanOrdinateRight3, "blue");
  218. SubFunction.TextShow(image, rightMian_Jicaitong * 0.2689, (int)middleRight, (int)meanOrdinateRight3+50);
  219. //上孔径标注
  220. SubFunction.LineShow(image, (int)aperture[0], (int)meanOrdinateLeft1 - 20, (int)aperture[1], (int)meanOrdinateLeft1-20, "blue");
  221. SubFunction.LineShow(image, aperture[0], (int)meanOrdinateLeft1 - 25, aperture[0], (int)meanOrdinateLeft1 - 15, "blue");
  222. SubFunction.LineShow(image, aperture[1], (int)meanOrdinateLeft1 - 25, aperture[1], (int)meanOrdinateLeft1 - 15, "blue");
  223. SubFunction.TextShow(image, shangKongjing * 0.2689, (int)middleAperture, (int)meanOrdinateLeft1 - 20);
  224. //下孔径标注
  225. SubFunction.LineShow(image, (int)apertureLow[0], (int)meanOrdinateLeft5 - 20, (int)apertureLow[1], (int)meanOrdinateLeft5 - 20, "blue");
  226. SubFunction.LineShow(image, apertureLow[0], (int)meanOrdinateLeft5 - 25, apertureLow[0], (int)meanOrdinateLeft5 - 15, "blue");
  227. SubFunction.LineShow(image, apertureLow[1], (int)meanOrdinateLeft5 - 25, apertureLow[1], (int)meanOrdinateLeft5 - 15, "blue");
  228. SubFunction.TextShow(image, xiaKongjing * 0.2689, (int)(apertureLow[0] + apertureLow[1]) / 2, (int)meanOrdinateLeft5 + 50);
  229. //孔铜标注
  230. //左
  231. SubFunction.LineShow(image, (int)aperture[0], (int)meanOrdinateLeft3, pointLeft[1], pointLeft[0], "blue");
  232. SubFunction.LineShow(image, aperture[0] - 5, (int)meanOrdinateLeft3, aperture[0] + 5, (int)meanOrdinateLeft3, "blue");
  233. SubFunction.LineShow(image, pointLeft[1] - 5, pointLeft[0], pointLeft[1] + 5, pointLeft[0], "blue");
  234. SubFunction.TextShow(image, leftKongtong * proportion, aperture[0], (int)meanOrdinateLeft3+20);
  235. //右
  236. SubFunction.LineShow(image, aperture[1], (int)meanOrdinateRight3, pointRight[1], pointRight[0], "blue");
  237. SubFunction.LineShow(image, aperture[1] - 5, (int)meanOrdinateRight3, aperture[1] + 5, (int)meanOrdinateRight3, "blue");
  238. SubFunction.LineShow(image, pointRight[1] - 5, pointRight[0], pointRight[1] + 5, pointRight[0], "blue");
  239. SubFunction.TextShow(image, rightKongtong * proportion, aperture[1], (int)meanOrdinateRight3+20);
  240. //孔深标注(浅盲孔没有孔深)
  241. //SubFunction.LineShow(image, (int)middleAperture, curveVertex[0], (int)middleAperture, (int)middleApertureY, "blue");
  242. //SubFunction.LineShow(image, (int)middleAperture - 5, curveVertex[0], (int)middleAperture + 5, curveVertex[0], "blue");
  243. //SubFunction.LineShow(image, (int)middleAperture - 5, (int)middleApertureY, (int)middleAperture + 5, (int)middleApertureY, "blue");
  244. //SubFunction.TextShow(image, kongshen * proportion, curveVertex[1], curveVertex[0]);
  245. //孔底标注
  246. double middlep = (meanOrdinateL6+meanOrdinateLeft1)/2;
  247. SubFunction.LineShow(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)meanOrdinateL6, "blue");
  248. SubFunction.LineShow(image, curveVertex[1] - 5, curveVertex[0], curveVertex[1] + 5, curveVertex[0], "blue");
  249. SubFunction.LineShow(image, curveVertex[1] - 5, (int)meanOrdinateL6, curveVertex[1] + 5, (int)meanOrdinateL6, "blue");
  250. SubFunction.TextShow(image, kongdi * proportion, curveVertex[1], (int)middlep);
  251. //左孔底咬食量
  252. SubFunction.LineShow(image, (int)middleLeft, (int)meanOrdinateLeft4, (int)middleLeft, (int)meanOrdinateL6, "blue");
  253. SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateLeft4, (int)middleLeft + 5, (int)meanOrdinateLeft4, "blue");
  254. SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateL6, (int)middleLeft + 5, (int)meanOrdinateL6, "blue");
  255. SubFunction.TextShow(image, leftKongdiyaoshiliang * proportion, (int)middleLeft, (int)meanOrdinateL6);
  256. //右孔底咬食量
  257. SubFunction.LineShow(image, (int)middleRight, (int)meanOrdinateRight4, (int)middleRight, (int)meanOrdinateL6, "blue");
  258. SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateRight4, (int)middleRight + 5, (int)meanOrdinateRight4, "blue");
  259. SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateL6, (int)middleRight + 5, (int)meanOrdinateL6, "blue");
  260. SubFunction.TextShow(image, rightKongdiyaoshiliang * proportion, (int)middleRight, (int)meanOrdinateL6);
  261. //拟合
  262. SubFunction.LineShow(image, apertureLow[0], (int)meanOrdinateL6, apertureLow[1], (int)meanOrdinateL6);
  263. SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft2, dataArea[1], (int)meanOrdinateLeft2);
  264. SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight2, dataArea[3], (int)meanOrdinateRight2);
  265. // 保存
  266. //Cv2.ImWrite(@"D:\eshi.jpg",image);
  267. // 显示
  268. new Window("demo1", WindowMode.Normal, image);
  269. Cv2.WaitKey(0);
  270. }
  271. public static void ShuangcengShenmangkong(string fileName)
  272. {
  273. // 获取图片
  274. Mat image = new Mat(fileName, ImreadModes.Color);
  275. // 转换为灰度图
  276. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  277. // 二值化,获得目标区域
  278. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  279. // 转换成数组
  280. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  281. arrayContour = BasFunction.ConversionRange(arrayContour);
  282. // 寻找两层分界点
  283. int[] sum = BasFunction.Sum(arrayContour, 2);// 每行求和
  284. int y1 = 0;// 上区域开始
  285. int y2 = 0;// 上区域结束
  286. int y3 = 0;// 下区域结束
  287. int y4 = 0;// 下区域开始
  288. for (int i = 0; i < imageContour.Rows; i++)
  289. {
  290. if (sum[i] > 0)
  291. {
  292. y1 = i;
  293. break;
  294. }
  295. }
  296. for (int i = imageContour.Rows - 1; i > 0; i--)
  297. {
  298. if (sum[i] > 0)
  299. {
  300. y4 = i;
  301. break;
  302. }
  303. }
  304. int[] newSum = BasFunction.Intercept(sum, y1, y4);
  305. int min = BasFunction.Min(newSum);
  306. for (int i = y1; i < y4; i++)
  307. {
  308. if (sum[i] < min + 50)
  309. {
  310. y2 = i;
  311. break;
  312. }
  313. }
  314. for (int i = y4; i > y2; i--)
  315. {
  316. if (sum[i] < min + 50)
  317. {
  318. y3 = i;
  319. break;
  320. }
  321. }
  322. int middle = (y2 + y3) / 2;// 分界点
  323. // 分成两份
  324. // 分原图
  325. Mat image1 = new Mat();
  326. Mat image2 = new Mat();
  327. BasFunction.InterceptMat(image, out image1, 0, middle, 0, image.Cols);
  328. BasFunction.InterceptMat(image, out image2, middle, image.Rows, 0, image.Cols);
  329. // 重新阈值分割
  330. Mat imageContour1 = image1.Threshold(0, 255, ThresholdTypes.Otsu);
  331. Mat imageContour2 = image2.Threshold(0, 255, ThresholdTypes.Otsu);
  332. // 对分好的图进行边缘检测
  333. Mat imageOutline1 = new Mat();
  334. Mat imageOutline2 = new Mat();
  335. SubFunction.Sobel(imageContour1, out imageOutline1);
  336. SubFunction.Sobel(imageContour2, out imageOutline2);
  337. // 对下方的图进行180度旋转
  338. Cv2.Flip(imageContour2, imageContour2, FlipMode.X);
  339. Cv2.Flip(imageOutline2, imageOutline2, FlipMode.X);
  340. // 调用
  341. Mat result1 = new Mat();
  342. Mat result2 = new Mat();
  343. DrawShenmangkong(image, out result1, imageContour1, imageOutline1);
  344. DrawShenmangkong2(result1, out result2, imageContour2, imageOutline2,middle);
  345. }
  346. public static void DancengShenmangkong(string fileName)
  347. {
  348. // 获取图片
  349. Mat image = new Mat(fileName, ImreadModes.Color);
  350. // 转换为灰度图
  351. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  352. // 二值化,获得目标区域
  353. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  354. // 闭运算,填充孔洞
  355. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));
  356. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  357. // 边缘检测
  358. Mat imageOutline = new Mat();
  359. SubFunction.Sobel(imageContour, out imageOutline);
  360. // 调用计算程序
  361. Mat result = new Mat();
  362. DrawShenmangkong(image, out result, imageContour, imageOutline);
  363. }
  364. public static void DrawShenmangkong(Mat image, out Mat result,Mat imageContour,Mat imageOutline)
  365. {
  366. // 一、预处理部分
  367. // 像素实际比例
  368. double proportion = 0.2689;
  369. // 得到行列数
  370. int rows = image.Rows;
  371. int cols = image.Cols;
  372. // 转换成灰度图
  373. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  374. // 获得蓝色,绿色,红色通道图片
  375. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  376. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  377. // 将Mat类转换成数组
  378. int[,] arrayOutline = BasFunction.Mat2Array(imageOutline);
  379. arrayOutline = BasFunction.ConversionRange(arrayOutline);//将数组转为0,1数组
  380. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  381. arrayContour = BasFunction.ConversionRange(arrayContour);
  382. // 二、计算中部区域的边界,middleArea[0]中部左边界,middleArea[1]中部右边界
  383. int[] middleArea = SubFunction.GetMiddleArea(imageContour);
  384. // 三、计算左右边界
  385. //dataArea[0]左部分左边界,dataArea[1]左部分右边界,dataArea[2]右部分左边界,dataArea[3]右部分右边界
  386. int[] dataArea = SubFunction.GetDataArea(imageContour, middleArea);
  387. // 四、提取L1,L3
  388. double meanOrdinateLeft1 = 0;// L1左部分纵坐标
  389. SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft1, dataArea[0], dataArea[1]);
  390. double meanOrdinateRight1 = 0;// L1右部分纵坐标
  391. SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight1, dataArea[2], dataArea[3]);
  392. double meanOrdinateLeft3 = 0;// L3左部分纵坐标
  393. SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1);
  394. double meanOrdinateRight3 = 0;// L3右部分纵坐标
  395. SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight3, dataArea[2], dataArea[3], meanOrdinateRight1);
  396. // 五、提取内部线L2
  397. double meanOrdinateLeft2 = 0;
  398. double meanOrdinateRight2 = 0;
  399. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2);
  400. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea[2], dataArea[3], out meanOrdinateRight2);
  401. // 六、提取L5,L6
  402. // 对轮廓线腐蚀
  403. Mat seErode = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 1));// 结构元素
  404. Mat imageOutlineErode = new Mat();// 腐蚀后轮廓线
  405. Cv2.Erode(imageOutline, imageOutlineErode, seErode);// 腐蚀
  406. // 转换成数组
  407. int[,] arrayOutlineErode = BasFunction.Mat2Array(imageOutlineErode);// 将Mat类转换成数组
  408. arrayOutlineErode = BasFunction.ConversionRange(arrayOutlineErode);//将数组转为0,1数组
  409. // 提取
  410. double meanOrdinateLeft5 = 0;// L5左部分
  411. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft5, dataArea[0], dataArea[1]-50,meanOrdinateLeft3);
  412. double meanOrdinateRight5 = 0;// L5右部分
  413. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight5, dataArea[2]+50, dataArea[3], meanOrdinateRight3);
  414. double meanOrdinateLeft6 = 0;// L6左部分
  415. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5);
  416. double meanOrdinateRight6 = 0;// L6右部分
  417. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight6, dataArea[2], dataArea[3], meanOrdinateRight5);
  418. // 七、提取胶体线
  419. Mat glue = new Mat();
  420. SubFunction.GlueArea(imageContour, imageRed, out glue, (int)meanOrdinateLeft3, (int)meanOrdinateLeft5,0,cols);
  421. // 转为数组
  422. int[,] arrayGlue = BasFunction.Mat2Array(glue);
  423. arrayGlue = BasFunction.ConversionRange(arrayGlue);
  424. // 八、提取L4
  425. double meanOrdinateLeft4 = 0;// L4左部分
  426. SubFunction.ExtractLines2(arrayGlue, out meanOrdinateLeft4, dataArea[0], dataArea[1]-50, meanOrdinateLeft5);
  427. double meanOrdinateRight4 = 0;// L4左部分
  428. SubFunction.ExtractLines2(arrayGlue, out meanOrdinateRight4, dataArea[2]+50, dataArea[3] , meanOrdinateRight5);
  429. // 九、计算孔径起止点
  430. //aperture[0]孔径起始点(左);aperture[1]孔径起始点(右)
  431. int[] aperture = new int[2];
  432. SubFunction.GetAperture(arrayContour, out aperture, (int)meanOrdinateLeft3, (int)meanOrdinateRight3, middleArea, dataArea);
  433. int[] apertureBegin = { (int)meanOrdinateLeft3, aperture[0] };// 孔径左边左边
  434. int[] apertureEnd = { (int)meanOrdinateRight3, aperture[1] };// 孔径右边左边
  435. double middleAperture = (aperture[0] + aperture[1]) / 2;//孔径中点
  436. // 十、计算孔铜
  437. // 得到曲面线条L1
  438. int[,] line1 = new int[rows, cols];
  439. double averageCoordinate1 = 0;//L1的纵坐标
  440. SubFunction.ExtractLines(arrayOutline, out line1, out averageCoordinate1, dataArea[0], dataArea[3]);
  441. //求孔径起始点与曲面之间的最短距离,以及最短距离时的曲面坐标
  442. double[] kongtong = new double[2];
  443. int[] pointLeft = new int[2];
  444. int[] pointRight = new int[2];
  445. SubFunction.GetKongtong(line1, apertureBegin, apertureEnd, out kongtong, out pointLeft, out pointRight);
  446. // 十一、计算胶内缩
  447. // 上胶边界
  448. int[] upperWaist = new int[2];
  449. SubFunction.GetWaist(imageContour, out upperWaist, (int)meanOrdinateLeft4 - 30, (int)meanOrdinateLeft4 + 30, (int)middleAperture);
  450. // 下胶边界
  451. int[] lowerWaist = new int[2];
  452. SubFunction.GetLowerWaist(imageContour, out lowerWaist, (int)meanOrdinateLeft4, (int)meanOrdinateLeft5, dataArea);
  453. // 十二 、提取L7
  454. double meanOrdinateL7 = 0;
  455. double t1 = 0;
  456. BasFunction.ChooseSize(meanOrdinateLeft5, meanOrdinateRight5, "small",out t1);
  457. SubFunction.InsideLine(imageGreen, (int)t1 - 10, (int)meanOrdinateLeft6 - 10, (int)middleAperture - 90, (int)middleAperture + 90, out meanOrdinateL7);
  458. // 十三、下孔径(这里用的是和上孔径一样的行数,但是上下边界的问题可能会有,需要注意)
  459. int[] lowerAperture = new int[2];
  460. SubFunction.GetAperture(arrayContour, out lowerAperture, (int)meanOrdinateLeft5, (int)meanOrdinateRight5, middleArea, dataArea);
  461. // 十四、曲面最凸点坐标
  462. int[] curveVertex = new int[2];
  463. double middleApertureY;//孔径平均高度
  464. SubFunction.CurveVertex(line1, apertureBegin, apertureEnd, out curveVertex, out middleApertureY);
  465. // 十五、计算
  466. double leftMiantong = meanOrdinateLeft2 - meanOrdinateLeft1;
  467. double rightMiantong = meanOrdinateRight2 - meanOrdinateRight1;
  468. double leftJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2;
  469. double rightJicaitong = meanOrdinateRight3 - meanOrdinateRight2;
  470. double leftMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1;
  471. double rightMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1;
  472. double leftJiaohou = meanOrdinateLeft5 - meanOrdinateLeft4;
  473. double rightJiaohou = meanOrdinateRight5 - meanOrdinateRight4;
  474. double leftKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateLeft5;
  475. double rightKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateRight5;
  476. double leftJiaoneisuo = upperWaist[0] - lowerWaist[0];
  477. double rightJiaoneisuo = lowerWaist[1] - upperWaist[1];
  478. double leftKongtong = kongtong[0];
  479. double rightKongtong = kongtong[1];
  480. double upperKongjing = aperture[1] - aperture[0];
  481. double lowerKongjing = lowerAperture[1] - lowerAperture[0];
  482. double kongshen = curveVertex[0] - middleApertureY;
  483. double kongdi = meanOrdinateL7 - curveVertex[0];
  484. // 十六、标记
  485. double middleLeft = (dataArea[0] + dataArea[1]) / 2;
  486. double middleRight = (dataArea[2] + dataArea[3]) / 2;
  487. // 左面铜
  488. SubFunction.LabelVertical(image, (int)middleLeft-20, (int)meanOrdinateLeft1, (int)middleLeft-20, (int)meanOrdinateLeft2, leftMiantong);
  489. // 右面铜
  490. SubFunction.LabelVertical(image, (int)middleRight+20, (int)meanOrdinateRight1, (int)middleRight+20, (int)meanOrdinateRight2, rightMiantong);
  491. // 左基材铜
  492. SubFunction.LabelVertical(image, (int)middleLeft - 40, (int)meanOrdinateLeft2, (int)middleLeft - 40, (int)meanOrdinateLeft3, leftJicaitong);
  493. // 右基材铜
  494. SubFunction.LabelVertical(image, (int)middleRight + 40, (int)meanOrdinateRight2, (int)middleRight + 40, (int)meanOrdinateRight3, rightJicaitong);
  495. // 左面铜+基材铜
  496. SubFunction.LabelVertical(image, (int)middleLeft, (int)meanOrdinateLeft1, (int)middleLeft, (int)meanOrdinateLeft3, leftMian_Jicaitong);
  497. // 右面铜+基材铜
  498. SubFunction.LabelVertical(image, (int)middleRight, (int)meanOrdinateRight1, (int)middleRight, (int)meanOrdinateRight3, rightMian_Jicaitong);
  499. // 左胶厚
  500. SubFunction.LabelVertical(image, (int)middleLeft, (int)meanOrdinateLeft4, (int)middleLeft, (int)meanOrdinateLeft5, leftJiaohou);
  501. // 右胶厚
  502. SubFunction.LabelVertical(image, (int)middleRight, (int)meanOrdinateRight4, (int)middleRight, (int)meanOrdinateRight5, rightJiaohou);
  503. // 左孔底咬食量
  504. SubFunction.LabelVertical(image, (int)middleLeft, (int)meanOrdinateLeft5, (int)middleLeft, (int)meanOrdinateL7, leftKongdiyaoshiliang);
  505. // 右孔底咬食量
  506. SubFunction.LabelVertical(image, (int)middleRight, (int)meanOrdinateRight5, (int)middleRight, (int)meanOrdinateL7, rightKongdiyaoshiliang);
  507. // 左胶内缩
  508. SubFunction.LableHorizontal(image, lowerWaist[0], (int)meanOrdinateLeft4, upperWaist[0], (int)meanOrdinateLeft4, leftJiaoneisuo);
  509. // 右胶内缩
  510. SubFunction.LableHorizontal(image, upperWaist[1], (int)meanOrdinateRight4, lowerWaist[1], (int)meanOrdinateRight4, rightJiaoneisuo);
  511. // 左孔铜
  512. SubFunction.LabelVertical(image, apertureBegin[1], apertureBegin[0], pointLeft[1], pointLeft[0], leftKongtong);
  513. // 右孔铜
  514. SubFunction.LabelVertical(image, apertureEnd[1], apertureEnd[0], pointRight[1], pointRight[0], rightKongtong);
  515. // 上孔径
  516. SubFunction.LableHorizontal(image, apertureBegin[1], (int)meanOrdinateLeft1 - 30, apertureEnd[1], (int)meanOrdinateLeft1 - 30, upperKongjing);
  517. // 下孔径
  518. SubFunction.LableHorizontal(image, lowerAperture[0], (int)meanOrdinateL7 + 20, lowerAperture[1], (int)meanOrdinateL7 + 20, lowerKongjing);
  519. // 孔深
  520. SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)middleApertureY, kongshen);
  521. // 孔底
  522. SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)meanOrdinateL7, kongdi);
  523. result = image;
  524. }
  525. public static void DrawShenmangkong2(Mat image, out Mat result, Mat imageContour, Mat imageOutline,int middle)
  526. {
  527. // 一、预处理部分
  528. // 像素实际比例
  529. double proportion = 0.2689;
  530. // 得到行列数
  531. int rows = image.Rows;
  532. int cols = image.Cols;
  533. // 转换成灰度图
  534. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  535. // 获得蓝色,绿色,红色通道图片
  536. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  537. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  538. // 将Mat类转换成数组
  539. int[,] arrayOutline = BasFunction.Mat2Array(imageOutline);
  540. arrayOutline = BasFunction.ConversionRange(arrayOutline);//将数组转为0,1数组
  541. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  542. arrayContour = BasFunction.ConversionRange(arrayContour);
  543. // 二、计算中部区域的边界,middleArea[0]中部左边界,middleArea[1]中部右边界
  544. int[] middleArea = SubFunction.GetMiddleArea(imageContour);
  545. // 三、计算左右边界
  546. //dataArea[0]左部分左边界,dataArea[1]左部分右边界,dataArea[2]右部分左边界,dataArea[3]右部分右边界
  547. int[] dataArea = SubFunction.GetDataArea(imageContour, middleArea);
  548. // 四、提取L1,L3
  549. double meanOrdinateLeft1 = 0;// L1左部分纵坐标
  550. SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft1, dataArea[0], dataArea[1]);
  551. double meanOrdinateRight1 = 0;// L1右部分纵坐标
  552. SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight1, dataArea[2], dataArea[3]);
  553. double meanOrdinateLeft3 = 0;// L3左部分纵坐标
  554. SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1);
  555. double meanOrdinateRight3 = 0;// L3右部分纵坐标
  556. SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight3, dataArea[2], dataArea[3], meanOrdinateRight1);
  557. // 五、提取内部线L2
  558. double meanOrdinateLeft2 = 0;
  559. double meanOrdinateRight2 = 0;
  560. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2);
  561. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea[2], dataArea[3], out meanOrdinateRight2);
  562. // 六、提取L5,L6
  563. // 对轮廓线腐蚀
  564. Mat seErode = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 1));// 结构元素
  565. Mat imageOutlineErode = new Mat();// 腐蚀后轮廓线
  566. Cv2.Erode(imageOutline, imageOutlineErode, seErode);// 腐蚀
  567. // 转换成数组
  568. int[,] arrayOutlineErode = BasFunction.Mat2Array(imageOutlineErode);// 将Mat类转换成数组
  569. arrayOutlineErode = BasFunction.ConversionRange(arrayOutlineErode);//将数组转为0,1数组
  570. // 提取
  571. double meanOrdinateLeft5 = 0;// L5左部分
  572. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft5, dataArea[0], dataArea[1] - 50, meanOrdinateLeft3);
  573. double meanOrdinateRight5 = 0;// L5右部分
  574. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight5, dataArea[2] + 50, dataArea[3], meanOrdinateRight3);
  575. double meanOrdinateLeft6 = 0;// L6左部分
  576. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5);
  577. double meanOrdinateRight6 = 0;// L6右部分
  578. SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight6, dataArea[2], dataArea[3], meanOrdinateRight5);
  579. // 七、提取胶体线
  580. Mat glue = new Mat();
  581. SubFunction.GlueArea(imageContour, imageRed, out glue, (int)meanOrdinateLeft3, (int)meanOrdinateLeft5,0,cols);
  582. // 转为数组
  583. int[,] arrayGlue = BasFunction.Mat2Array(glue);
  584. arrayGlue = BasFunction.ConversionRange(arrayGlue);
  585. // 八、提取L4
  586. double meanOrdinateLeft4 = 0;// L4左部分
  587. SubFunction.ExtractLines2(arrayGlue, out meanOrdinateLeft4, dataArea[0], dataArea[1] - 50, meanOrdinateLeft5);
  588. double meanOrdinateRight4 = 0;// L4左部分
  589. SubFunction.ExtractLines2(arrayGlue, out meanOrdinateRight4, dataArea[2] + 50, dataArea[3], meanOrdinateRight5);
  590. // 九、计算孔径起止点
  591. //aperture[0]孔径起始点(左);aperture[1]孔径起始点(右)
  592. int[] aperture = new int[2];
  593. SubFunction.GetAperture(arrayContour, out aperture, (int)meanOrdinateLeft3, (int)meanOrdinateRight3, middleArea, dataArea);
  594. int[] apertureBegin = { (int)meanOrdinateLeft3, aperture[0] };// 孔径左边左边
  595. int[] apertureEnd = { (int)meanOrdinateRight3, aperture[1] };// 孔径右边左边
  596. double middleAperture = (aperture[0] + aperture[1]) / 2;//孔径中点
  597. // 十、计算孔铜
  598. // 得到曲面线条L1
  599. int[,] line1 = new int[rows, cols];
  600. double averageCoordinate1 = 0;//L1的纵坐标
  601. SubFunction.ExtractLines(arrayOutline, out line1, out averageCoordinate1, dataArea[0], dataArea[3]);
  602. //求孔径起始点与曲面之间的最短距离,以及最短距离时的曲面坐标
  603. double[] kongtong = new double[2];
  604. int[] pointLeft = new int[2];
  605. int[] pointRight = new int[2];
  606. SubFunction.GetKongtong(line1, apertureBegin, apertureEnd, out kongtong, out pointLeft, out pointRight);
  607. // 十一、计算胶内缩
  608. // 上胶边界
  609. int[] upperWaist = new int[2];
  610. SubFunction.GetWaist(imageContour, out upperWaist, (int)meanOrdinateLeft4 - 30, (int)meanOrdinateLeft4 + 30, (int)middleAperture);
  611. // 下胶边界
  612. int[] lowerWaist = new int[2];
  613. SubFunction.GetLowerWaist(imageContour, out lowerWaist, (int)meanOrdinateLeft4, (int)meanOrdinateLeft5, dataArea);
  614. // 十二 、提取L7
  615. double meanOrdinateL7 = 0;
  616. double t1 = 0;
  617. BasFunction.ChooseSize(meanOrdinateLeft5, meanOrdinateRight5, "small", out t1);
  618. SubFunction.InsideLine(imageGreen, (int)t1 - 10, (int)meanOrdinateLeft6 - 10, (int)middleAperture - 90, (int)middleAperture + 90, out meanOrdinateL7);
  619. // 十三、下孔径(这里用的是和上孔径一样的行数,但是上下边界的问题可能会有,需要注意)
  620. int[] lowerAperture = new int[2];
  621. SubFunction.GetAperture(arrayContour, out lowerAperture, (int)meanOrdinateLeft5, (int)meanOrdinateRight5, middleArea, dataArea);
  622. // 十四、曲面最凸点坐标
  623. int[] curveVertex = new int[2];
  624. double middleApertureY;//孔径平均高度
  625. SubFunction.CurveVertex(line1, apertureBegin, apertureEnd, out curveVertex, out middleApertureY);
  626. // 十五、计算
  627. double leftMiantong = meanOrdinateLeft2 - meanOrdinateLeft1;
  628. double rightMiantong = meanOrdinateRight2 - meanOrdinateRight1;
  629. double leftJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2;
  630. double rightJicaitong = meanOrdinateRight3 - meanOrdinateRight2;
  631. double leftMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1;
  632. double rightMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1;
  633. double leftJiaohou = meanOrdinateLeft5 - meanOrdinateLeft4;
  634. double rightJiaohou = meanOrdinateRight5 - meanOrdinateRight4;
  635. double leftKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateLeft5;
  636. double rightKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateRight5;
  637. double leftJiaoneisuo = upperWaist[0] - lowerWaist[0];
  638. double rightJiaoneisuo = lowerWaist[1] - upperWaist[1];
  639. double leftKongtong = kongtong[0];
  640. double rightKongtong = kongtong[1];
  641. double upperKongjing = aperture[1] - aperture[0];
  642. double lowerKongjing = lowerAperture[1] - lowerAperture[0];
  643. double kongshen = curveVertex[0] - middleApertureY;
  644. double kongdi = meanOrdinateL7 - curveVertex[0];
  645. // 十六、标记
  646. double middleLeft = (dataArea[0] + dataArea[1]) / 2;
  647. double middleRight = (dataArea[2] + dataArea[3]) / 2;
  648. // 左面铜
  649. SubFunction.LabelVertical(image, (int)middleLeft - 20, (int)(2*middle-meanOrdinateLeft1), (int)middleLeft - 20, (int)(2 * middle - meanOrdinateLeft2), leftMiantong);
  650. // 右面铜
  651. SubFunction.LabelVertical(image, (int)middleRight + 20, (int)(2 * middle - meanOrdinateRight1), (int)middleRight + 20, (int)(2 * middle - meanOrdinateRight2), rightMiantong);
  652. // 左基材铜
  653. SubFunction.LabelVertical(image, (int)middleLeft - 40, (int)(2 * middle - meanOrdinateLeft2), (int)middleLeft - 40, (int)(2 * middle - meanOrdinateLeft3), leftJicaitong);
  654. // 右基材铜
  655. SubFunction.LabelVertical(image, (int)middleRight + 40, (int)(2 * middle - meanOrdinateRight2), (int)middleRight + 40, (int)(2 * middle - meanOrdinateRight3), rightJicaitong);
  656. // 左面铜+基材铜
  657. SubFunction.LabelVertical(image, (int)middleLeft, (int)(2 * middle - meanOrdinateLeft1), (int)middleLeft, (int)(2 * middle - meanOrdinateLeft3), leftMian_Jicaitong);
  658. // 右面铜+基材铜
  659. SubFunction.LabelVertical(image, (int)middleRight, (int)(2 * middle - meanOrdinateRight1), (int)middleRight, (int)(2 * middle - meanOrdinateRight3), rightMian_Jicaitong);
  660. // 左胶厚
  661. SubFunction.LabelVertical(image, (int)middleLeft, (int)(2 * middle - meanOrdinateLeft4), (int)middleLeft, (int)(2 * middle - meanOrdinateLeft5), leftJiaohou);
  662. // 右胶厚
  663. SubFunction.LabelVertical(image, (int)middleRight, (int)(2 * middle - meanOrdinateRight4), (int)middleRight, (int)(2 * middle - meanOrdinateRight5), rightJiaohou);
  664. // 左孔底咬食量
  665. SubFunction.LabelVertical(image, (int)middleLeft, (int)(2 * middle - meanOrdinateLeft5), (int)middleLeft, (int)(2 * middle - meanOrdinateL7), leftKongdiyaoshiliang);
  666. // 右孔底咬食量
  667. SubFunction.LabelVertical(image, (int)middleRight, (int)(2 * middle - meanOrdinateRight5), (int)middleRight, (int)(2 * middle - meanOrdinateL7), rightKongdiyaoshiliang);
  668. // 左胶内缩
  669. SubFunction.LableHorizontal(image, lowerWaist[0], (int)(2 * middle - meanOrdinateLeft4), upperWaist[0], (int)(2 * middle - meanOrdinateLeft4), leftJiaoneisuo);
  670. // 右胶内缩
  671. SubFunction.LableHorizontal(image, upperWaist[1], (int)(2 * middle - meanOrdinateRight4), lowerWaist[1], (int)(2 * middle - meanOrdinateRight4), rightJiaoneisuo);
  672. // 左孔铜
  673. SubFunction.LabelVertical(image, apertureBegin[1], (2 * middle - apertureBegin[0]), pointLeft[1], (2 * middle - pointLeft[0]), leftKongtong);
  674. // 右孔铜
  675. SubFunction.LabelVertical(image, apertureEnd[1], (2 * middle - apertureEnd[0]), pointRight[1], (2 * middle - pointRight[0]), rightKongtong);
  676. // 上孔径
  677. SubFunction.LableHorizontal(image, apertureBegin[1], (int)(2 * middle - (meanOrdinateLeft1 - 30)), apertureEnd[1], (int)(2 * middle - (meanOrdinateLeft1 - 30)), upperKongjing);
  678. // 下孔径
  679. SubFunction.LableHorizontal(image, lowerAperture[0], (int)(2 * middle - (meanOrdinateL7 + 20)), lowerAperture[1], (int)(2 * middle - (meanOrdinateL7 + 20)), lowerKongjing);
  680. // 孔深
  681. SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)(2 * middle - middleApertureY), kongshen);
  682. // 孔底
  683. SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)(2 * middle - meanOrdinateL7), kongdi);
  684. result = image;
  685. }
  686. public static void CaokongShuangcengYou(string fileName)
  687. {
  688. // 一、预处理
  689. // 读取图片
  690. Mat image = new Mat(fileName, ImreadModes.Color);
  691. //获取图片的长宽
  692. int rows = image.Rows;
  693. int cols = image.Cols;
  694. // 转换为灰度图
  695. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  696. //获得蓝色,绿色,红色通道图片
  697. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  698. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  699. // 二值化,获得目标区域
  700. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  701. // 闭运算,消除小孔
  702. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  703. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  704. // 转成数组
  705. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  706. arrayContour = BasFunction.ConversionRange(arrayContour);
  707. // 去亮光
  708. int b2, b3;
  709. SubFunction.SplitArea(arrayContour, out b2, out b3);
  710. if ((b3 - b2) > 100)
  711. {
  712. Mat result = new Mat();
  713. BasFunction.SetNumber(imageContour, out result, 0, rows, 0, b3, 0);// 亮光区域置0
  714. imageContour = result;
  715. }
  716. // 边缘检测
  717. Mat imageOutlint = new Mat();
  718. SubFunction.Sobel(imageContour, out imageOutlint);
  719. int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint);
  720. arrayOutline = BasFunction.ConversionRange(arrayOutline);
  721. // 二、计算数据提取区域
  722. // 对图片进行填充
  723. Mat imageFill = new Mat();
  724. SubFunction.Fill(imageContour, out imageFill);
  725. // 计算数据提取区域
  726. int[] dataArea = new int[2];
  727. SubFunction.DataArea2(imageFill, out dataArea);
  728. // 三、提取L1,L3,L4,L6
  729. double meanOrdinateL1 = 0;
  730. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]);
  731. double meanOrdinateL3 = 0;
  732. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1],meanOrdinateL1);
  733. double meanOrdinateL4 = 0;
  734. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3);
  735. double meanOrdinateL6 = 0;
  736. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL4);
  737. // 四、提取L2
  738. double meanOrdinateL2 = 0;
  739. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2);
  740. // 五、提取L5
  741. double meanOrdinateL5 = 0;
  742. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL4 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1], out meanOrdinateL5);
  743. // 六、提竖线V1,V2
  744. double abscissaV1 = 0;
  745. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4);
  746. double abscissaV2 = 0;
  747. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1);
  748. // 七、数据计算
  749. double upperMiantong = meanOrdinateL2 - meanOrdinateL1;
  750. double upperJicaitong = meanOrdinateL3 - meanOrdinateL2;
  751. double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1;
  752. double lowerMiantong = meanOrdinateL6 - meanOrdinateL5;
  753. double lowerJicaitong = meanOrdinateL5 - meanOrdinateL4;
  754. double lowerMian_Jicaitong = meanOrdinateL6 - meanOrdinateL4;
  755. double kongtong = abscissaV2 - abscissaV1;
  756. // 八、标记
  757. int middle = (dataArea[0] + dataArea[1]) / 2;
  758. int middle2 = (int)((meanOrdinateL3 + meanOrdinateL4) / 2);
  759. // 上面铜
  760. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL1, middle + 40, (int)meanOrdinateL2,upperMiantong);
  761. // 上基材铜
  762. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL2, middle - 40, (int)meanOrdinateL3, upperJicaitong);
  763. // 上面铜+基材铜
  764. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong);
  765. // 下面铜
  766. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL5, middle + 40, (int)meanOrdinateL6, lowerMiantong);
  767. // 下基材铜
  768. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL4, middle - 40, (int)meanOrdinateL5, lowerJicaitong);
  769. // 下面铜+基材铜
  770. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL4, middle, (int)meanOrdinateL6, lowerMian_Jicaitong);
  771. // 孔铜
  772. SubFunction.LableHorizontal(image, (int)abscissaV2, middle2, (int)abscissaV1, middle2, kongtong);
  773. }
  774. public static void CaokongShuangcengZuo(string fileName)
  775. {
  776. // 一、预处理
  777. // 读取图片
  778. Mat image = new Mat(fileName, ImreadModes.Color);
  779. //获取图片的长宽
  780. int rows = image.Rows;
  781. int cols = image.Cols;
  782. // 转换为灰度图
  783. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  784. //获得蓝色,绿色,红色通道图片
  785. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  786. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  787. // 二值化,获得目标区域
  788. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  789. // 闭运算,消除小孔
  790. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  791. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  792. // 转成数组
  793. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  794. arrayContour = BasFunction.ConversionRange(arrayContour);
  795. // 去亮光
  796. int b2, b3;
  797. SubFunction.SplitArea(arrayContour, out b2, out b3);
  798. if ((b3 - b2) > 100)
  799. {
  800. Mat result = new Mat();
  801. BasFunction.SetNumber(imageContour, out result, 0, rows, b2, cols, 0);// 亮光区域置0
  802. imageContour = result;
  803. }
  804. // 边缘检测
  805. Mat imageOutlint = new Mat();
  806. SubFunction.Sobel(imageContour, out imageOutlint);
  807. int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint);
  808. arrayOutline = BasFunction.ConversionRange(arrayOutline);
  809. // 二、计算数据提取区域
  810. // 对图片进行填充
  811. Mat imageFill = new Mat();
  812. SubFunction.Fill(imageContour, out imageFill);
  813. // 计算数据提取区域
  814. int[] dataArea = new int[2];
  815. SubFunction.DataArea2(imageFill, out dataArea);
  816. // 三、提取L1,L3,L4,L6
  817. double meanOrdinateL1 = 0;
  818. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]);
  819. double meanOrdinateL3 = 0;
  820. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1);
  821. double meanOrdinateL4 = 0;
  822. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3);
  823. double meanOrdinateL6 = 0;
  824. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL4);
  825. // 四、提取L2
  826. double meanOrdinateL2 = 0;
  827. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2);
  828. // 五、提取L5
  829. double meanOrdinateL5 = 0;
  830. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL4 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1], out meanOrdinateL5);
  831. // 六、提竖线V1,V2
  832. double abscissaV1 = 0;
  833. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4);
  834. double abscissaV2 = 0;
  835. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1);
  836. // 七、数据计算
  837. double upperMiantong = meanOrdinateL2 - meanOrdinateL1;
  838. double upperJicaitong = meanOrdinateL3 - meanOrdinateL2;
  839. double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1;
  840. double lowerMiantong = meanOrdinateL6 - meanOrdinateL5;
  841. double lowerJicaitong = meanOrdinateL5 - meanOrdinateL4;
  842. double lowerMian_Jicaitong = meanOrdinateL6 - meanOrdinateL4;
  843. double kongtong = abscissaV1 - abscissaV2;
  844. // 八、标记
  845. int middle = (dataArea[0] + dataArea[1]) / 2;
  846. int middle2 = (int)((meanOrdinateL3 + meanOrdinateL4) / 2);
  847. // 上面铜
  848. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL1, middle + 40, (int)meanOrdinateL2, upperMiantong);
  849. // 上基材铜
  850. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL2, middle - 40, (int)meanOrdinateL3, upperJicaitong);
  851. // 上面铜+基材铜
  852. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong);
  853. // 下面铜
  854. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL5, middle + 40, (int)meanOrdinateL6, lowerMiantong);
  855. // 下基材铜
  856. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL4, middle - 40, (int)meanOrdinateL5, lowerJicaitong);
  857. // 下面铜+基材铜
  858. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL4, middle, (int)meanOrdinateL6, lowerMian_Jicaitong);
  859. // 孔铜
  860. SubFunction.LableHorizontal(image, (int)abscissaV2, middle2, (int)abscissaV1, middle2, kongtong);
  861. }
  862. public static void CaokongSancengYou(string fileName)
  863. {
  864. // 一、预处理
  865. // 读取图片
  866. Mat image = new Mat(fileName, ImreadModes.Color);
  867. //获取图片的长宽
  868. int rows = image.Rows;
  869. int cols = image.Cols;
  870. // 转换为灰度图
  871. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  872. //获得蓝色,绿色,红色通道图片
  873. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  874. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  875. // 二值化,获得目标区域
  876. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  877. // 闭运算,消除小孔
  878. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  879. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  880. // 转成数组
  881. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  882. arrayContour = BasFunction.ConversionRange(arrayContour);
  883. // 去亮光
  884. int b2, b3;
  885. SubFunction.SplitArea(arrayContour, out b2, out b3);
  886. if ((b3 - b2) > 100)
  887. {
  888. Mat result = new Mat();
  889. BasFunction.SetNumber(imageContour, out result, 0, rows, 0, b3, 0);// 亮光区域置0
  890. imageContour = result;
  891. }
  892. // 边缘检测
  893. Mat imageOutlint = new Mat();
  894. SubFunction.Sobel(imageContour, out imageOutlint);
  895. int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint);
  896. arrayOutline = BasFunction.ConversionRange(arrayOutline);
  897. // 二、计算数据提取区域
  898. // 对图片进行填充
  899. Mat imageFill = new Mat();
  900. SubFunction.Fill(imageContour, out imageFill);
  901. // 计算数据提取区域
  902. int[] dataArea = new int[2];
  903. SubFunction.DataArea2(imageFill, out dataArea);
  904. // 三、提取L1,L3,L4,L5, L6, L8
  905. double meanOrdinateL1 = 0;
  906. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]);
  907. double meanOrdinateL3 = 0;
  908. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1);
  909. double meanOrdinateL4 = 0;
  910. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3);
  911. double meanOrdinateL5 = 0;
  912. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4);
  913. double meanOrdinateL6 = 0;
  914. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5);
  915. double meanOrdinateL8 = 0;
  916. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL8, dataArea[0], dataArea[1], meanOrdinateL6);
  917. // 四、提取L2
  918. double meanOrdinateL2 = 0;
  919. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2);
  920. // 五、提取L7
  921. double meanOrdinateL7 = 0;
  922. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL6 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1], out meanOrdinateL7);
  923. // 六、提取胶体线
  924. Mat imageGlue = new Mat();
  925. SubFunction.GlueArea(imageContour, imageRed, out imageGlue, (int)meanOrdinateL5 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1]);
  926. // 转数组
  927. int[,] arrayGlue = BasFunction.Mat2Array(imageGlue);
  928. arrayGlue = BasFunction.ConversionRange(arrayGlue);
  929. // 提取胶体线
  930. double meanOrdinateLG = 0;
  931. SubFunction.InsideLine(imageGlue, (int)meanOrdinateL5 + 15, (int)meanOrdinateL6 - 15, dataArea[0], dataArea[1], out meanOrdinateLG);
  932. // 七、提取竖线V1、V2、V3、V4
  933. double abscissaV1 = 0;
  934. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4);
  935. double abscissaV2 = 0;
  936. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1);
  937. double abscissaV3 = 0;
  938. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV3, (int)meanOrdinateLG, (int)meanOrdinateL6);
  939. double abscissaV4 = 0;
  940. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV4, (int)meanOrdinateLG, (int)meanOrdinateL6, abscissaV3);
  941. // 八、计算粗糙度
  942. int cucaodu;
  943. int[] cucaoduZuobiao = new int[2];
  944. SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL5 + 60, (int)meanOrdinateL6 - 30, (int)abscissaV4, out cucaodu, out cucaoduZuobiao);
  945. // 九、计算数据
  946. double upperMiantong = meanOrdinateL2 - meanOrdinateL1;
  947. double upperJicaitong = meanOrdinateL3 - meanOrdinateL2;
  948. double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1;
  949. double lowerMiantong = meanOrdinateL8 - meanOrdinateL7;
  950. double lowerJicaitong = meanOrdinateL7 - meanOrdinateL6;
  951. double lowerMian_Jicaitong = meanOrdinateL8 - meanOrdinateL6;
  952. double upperKongtong = abscissaV2 - abscissaV1;
  953. double lowerKongtong = abscissaV4 - abscissaV3;
  954. // 十、标记
  955. int middle = (dataArea[0] + dataArea[1]) / 2;
  956. int middle2 = (int)(meanOrdinateL3 + meanOrdinateL4) / 2;
  957. int middle3 = (int)(meanOrdinateLG + meanOrdinateL6) / 2;
  958. // 上面铜
  959. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong);
  960. // 上基材铜
  961. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong);
  962. // 上面铜+基材铜
  963. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong);
  964. // 下面铜
  965. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong);
  966. // 下基材铜
  967. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong);
  968. // 下面铜+基材铜
  969. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong);
  970. // 上孔铜
  971. SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong);
  972. // 下孔铜
  973. SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, lowerKongtong);
  974. // 粗糙度
  975. SubFunction.LableHorizontal(image, (int)abscissaV4, cucaoduZuobiao[0], cucaoduZuobiao[1], cucaoduZuobiao[0], cucaodu);
  976. }
  977. public static void CaokongSancengZuo(string fileName)
  978. {
  979. // 一、预处理
  980. // 读取图片
  981. Mat image = new Mat(fileName, ImreadModes.Color);
  982. //获取图片的长宽
  983. int rows = image.Rows;
  984. int cols = image.Cols;
  985. // 转换为灰度图
  986. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  987. //获得蓝色,绿色,红色通道图片
  988. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  989. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  990. // 二值化,获得目标区域
  991. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  992. // 闭运算,消除小孔
  993. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  994. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  995. // 转成数组
  996. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  997. arrayContour = BasFunction.ConversionRange(arrayContour);
  998. // 去亮光
  999. int b2, b3;
  1000. SubFunction.SplitArea(arrayContour, out b2, out b3);
  1001. if ((b3 - b2) > 100)
  1002. {
  1003. Mat result = new Mat();
  1004. BasFunction.SetNumber(imageContour, out result, 0, rows, b2, cols, 0);// 亮光区域置0
  1005. imageContour = result;
  1006. }
  1007. // 边缘检测
  1008. Mat imageOutlint = new Mat();
  1009. SubFunction.Sobel(imageContour, out imageOutlint);
  1010. int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint);
  1011. arrayOutline = BasFunction.ConversionRange(arrayOutline);
  1012. // 二、计算数据提取区域
  1013. // 对图片进行填充
  1014. Mat imageFill = new Mat();
  1015. SubFunction.Fill(imageContour, out imageFill);
  1016. // 计算数据提取区域
  1017. int[] dataArea = new int[2];
  1018. SubFunction.DataArea2(imageFill, out dataArea);
  1019. // 三、提取L1,L3,L4,L5, L6, L8
  1020. double meanOrdinateL1 = 0;
  1021. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]);
  1022. double meanOrdinateL3 = 0;
  1023. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1);
  1024. double meanOrdinateL4 = 0;
  1025. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3);
  1026. double meanOrdinateL5 = 0;
  1027. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4);
  1028. double meanOrdinateL6 = 0;
  1029. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5);
  1030. double meanOrdinateL8 = 0;
  1031. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL8);
  1032. // 四、提取L2
  1033. double meanOrdinateL2 = 0;
  1034. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2);
  1035. // 五、提取L7
  1036. double meanOrdinateL7 = 0;
  1037. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL6 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1], out meanOrdinateL7);
  1038. // 六、提取胶体线
  1039. Mat imageGlue = new Mat();
  1040. SubFunction.GlueArea(imageContour, imageRed, out imageGlue, (int)meanOrdinateL5 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1]);
  1041. // 转数组
  1042. int[,] arrayGlue = BasFunction.Mat2Array(imageGlue);
  1043. arrayGlue = BasFunction.ConversionRange(arrayGlue);
  1044. // 提取胶体线
  1045. double meanOrdinateLG = 0;
  1046. SubFunction.InsideLine(imageGlue, (int)meanOrdinateL5 + 15, (int)meanOrdinateL6 - 15, dataArea[0], dataArea[1], out meanOrdinateLG);
  1047. // 七、提取竖线V1、V2、V3、V4
  1048. double abscissaV1 = 0;
  1049. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4);
  1050. double abscissaV2 = 0;
  1051. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1);
  1052. double abscissaV3 = 0;
  1053. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV3, (int)meanOrdinateLG, (int)meanOrdinateL6);
  1054. double abscissaV4 = 0;
  1055. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV4, (int)meanOrdinateLG, (int)meanOrdinateL6, abscissaV3);
  1056. // 八、计算粗糙度
  1057. int cucaodu;
  1058. int[] cucaoduZuobiao = new int[2];
  1059. SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL5 + 60, (int)meanOrdinateL6 - 30, (int)abscissaV4, out cucaodu, out cucaoduZuobiao);
  1060. // 九、计算数据
  1061. double upperMiantong = meanOrdinateL2 - meanOrdinateL1;
  1062. double upperJicaitong = meanOrdinateL3 - meanOrdinateL2;
  1063. double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1;
  1064. double lowerMiantong = meanOrdinateL8 - meanOrdinateL7;
  1065. double lowerJicaitong = meanOrdinateL7 - meanOrdinateL6;
  1066. double lowerMian_Jicaitong = meanOrdinateL8 - meanOrdinateL6;
  1067. double upperKongtong = abscissaV1 - abscissaV2;
  1068. double lowerKongtong = abscissaV3 - abscissaV4;
  1069. // 十、标记
  1070. int middle = (dataArea[0] + dataArea[1]) / 2;
  1071. int middle2 = (int)(meanOrdinateL3 + meanOrdinateL4) / 2;
  1072. int middle3 = (int)(meanOrdinateLG + meanOrdinateL6) / 2;
  1073. // 上面铜
  1074. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong);
  1075. // 上基材铜
  1076. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong);
  1077. // 上面铜+基材铜
  1078. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong);
  1079. // 下面铜
  1080. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong);
  1081. // 下基材铜
  1082. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong);
  1083. // 下面铜+基材铜
  1084. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong);
  1085. // 上孔铜
  1086. SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong);
  1087. // 下孔铜
  1088. SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, lowerKongtong);
  1089. // 粗糙度
  1090. SubFunction.LableHorizontal(image, (int)abscissaV4, cucaoduZuobiao[0], cucaoduZuobiao[1], cucaoduZuobiao[0], cucaodu);
  1091. }
  1092. public static void CaokongSicengYou(string fileName)
  1093. {
  1094. // 一、预处理
  1095. // 读取图片
  1096. Mat image = new Mat(fileName, ImreadModes.Color);
  1097. //获取图片的长宽
  1098. int rows = image.Rows;
  1099. int cols = image.Cols;
  1100. // 转换为灰度图
  1101. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  1102. //获得蓝色,绿色,红色通道图片
  1103. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  1104. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  1105. // 二值化,获得目标区域
  1106. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  1107. // 闭运算,消除小孔
  1108. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  1109. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  1110. // 去亮光
  1111. Mat result = new Mat();
  1112. SubFunction.RemoveLightSiceng(imageContour, imageRed, out result, "right");
  1113. imageContour = result;
  1114. // 转成数组
  1115. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  1116. arrayContour = BasFunction.ConversionRange(arrayContour);
  1117. // 边缘检测
  1118. Mat imageOutlint = new Mat();
  1119. SubFunction.Sobel(imageContour, out imageOutlint);
  1120. int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint);
  1121. arrayOutline = BasFunction.ConversionRange(arrayOutline);
  1122. // 二、计算数据提取区域
  1123. // 对图片进行填充
  1124. Mat imageFill = new Mat();
  1125. SubFunction.Fill(imageContour, out imageFill);
  1126. // 计算数据提取区域
  1127. int[] dataArea = new int[2];
  1128. SubFunction.DataArea2(imageFill, out dataArea);
  1129. // 三、提取L1,L3,L4,L5, L6, L7, L8, L10
  1130. double meanOrdinateL1 = 0;
  1131. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]);
  1132. double meanOrdinateL3 = 0;
  1133. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1);
  1134. double meanOrdinateL4 = 0;
  1135. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3);
  1136. double meanOrdinateL5 = 0;
  1137. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4);
  1138. double meanOrdinateL6 = 0;
  1139. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5);
  1140. double meanOrdinateL7 = 0;
  1141. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL7, dataArea[0], dataArea[1], meanOrdinateL6);
  1142. double meanOrdinateL8 = 0;
  1143. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL8, dataArea[0], dataArea[1], meanOrdinateL7);
  1144. double meanOrdinateL10 = 0;
  1145. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL10, dataArea[0], dataArea[1], meanOrdinateL8);
  1146. // 四、提取L2
  1147. double meanOrdinateL2 = 0;
  1148. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2);
  1149. // 五、提取L7
  1150. double meanOrdinateL9 = 0;
  1151. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL8 + 10, (int)meanOrdinateL10 - 10, dataArea[0], dataArea[1], out meanOrdinateL10);
  1152. // 六、提取胶体线
  1153. Mat imageGlue1 = new Mat();
  1154. SubFunction.GlueArea(imageContour, imageRed, out imageGlue1, (int)meanOrdinateL3 + 10, (int)meanOrdinateL4 - 10, dataArea[0], dataArea[1]);
  1155. Mat imageGlue2 = new Mat();
  1156. SubFunction.GlueArea(imageContour, imageRed, out imageGlue2, (int)meanOrdinateL7 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1]);
  1157. // 转数组
  1158. int[,] arrayGlue1 = BasFunction.Mat2Array(imageGlue1);
  1159. arrayGlue1 = BasFunction.ConversionRange(arrayGlue1);
  1160. int[,] arrayGlue2 = BasFunction.Mat2Array(imageGlue2);
  1161. arrayGlue2 = BasFunction.ConversionRange(arrayGlue2);
  1162. // 提取胶体线
  1163. double meanOrdinateLG1 = 0;
  1164. SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL3 + 15, (int)meanOrdinateL4 - 15, dataArea[0], dataArea[1], out meanOrdinateLG1);
  1165. double meanOrdinateLG2 = 0;
  1166. SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL7 + 15, (int)meanOrdinateL8 - 15, dataArea[0], dataArea[1], out meanOrdinateLG2);
  1167. // 七、提取竖线V1、V2、V3、V4、V5、V6
  1168. double abscissaV1 = 0;
  1169. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateLG1);
  1170. double abscissaV2 = 0;
  1171. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateLG1, abscissaV1);
  1172. double abscissaV3 = 0;
  1173. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV3, (int)meanOrdinateL5, (int)meanOrdinateL6);
  1174. double abscissaV4 = 0;
  1175. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV4, (int)meanOrdinateL5, (int)meanOrdinateL6, abscissaV3);
  1176. double abscissaV5 = 0;
  1177. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV5, (int)meanOrdinateLG2, (int)meanOrdinateL8);
  1178. double abscissaV6 = 0;
  1179. SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV6, (int)meanOrdinateLG2, (int)meanOrdinateL8, abscissaV5);
  1180. // 八、计算粗糙度
  1181. int cucaodu1;
  1182. int[] cucaoduZuobiao1 = new int[2];
  1183. SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL3 + 60, (int)meanOrdinateL4 - 30, (int)abscissaV2, out cucaodu1, out cucaoduZuobiao1);
  1184. int cucaodu2;
  1185. int[] cucaoduZuobiao2 = new int[2];
  1186. SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL7 + 60, (int)meanOrdinateL8 - 30, (int)abscissaV6, out cucaodu2, out cucaoduZuobiao2);
  1187. // 九、计算数据
  1188. double upperMiantong = meanOrdinateL2 - meanOrdinateL1;
  1189. double upperJicaitong = meanOrdinateL3 - meanOrdinateL2;
  1190. double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1;
  1191. double lowerMiantong = meanOrdinateL10 - meanOrdinateL8;
  1192. double lowerJicaitong = meanOrdinateL9 - meanOrdinateL8;
  1193. double lowerMian_Jicaitong = meanOrdinateL10 - meanOrdinateL8;
  1194. double upperKongtong = abscissaV2 - abscissaV1;
  1195. double middleKongtong = abscissaV4 - abscissaV3;
  1196. double lowerKongtong = abscissaV6 - abscissaV5;
  1197. // 十、标记
  1198. int middle = (dataArea[0] + dataArea[1]) / 2;// 面铜+基材铜横坐标
  1199. int middle2 = (int)(meanOrdinateL3 + meanOrdinateLG1) / 2;// 孔铜1纵坐标
  1200. int middle3 = (int)(meanOrdinateL5 + meanOrdinateL6) / 2;// 孔铜2纵坐标
  1201. int middle4 = (int)(meanOrdinateLG2 + meanOrdinateL8) / 2;// 孔铜3纵坐标
  1202. // 上面铜
  1203. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong);
  1204. // 上基材铜
  1205. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong);
  1206. // 上面铜+基材铜
  1207. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong);
  1208. // 下面铜
  1209. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong);
  1210. // 下基材铜
  1211. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong);
  1212. // 下面铜+基材铜
  1213. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong);
  1214. // 上孔铜
  1215. SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong);
  1216. // 中孔铜
  1217. SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, middleKongtong);
  1218. // 下孔铜
  1219. SubFunction.LableHorizontal(image, (int)abscissaV5, middle4, (int)abscissaV6, middle4, lowerKongtong);
  1220. // 粗糙度1
  1221. SubFunction.LableHorizontal(image, (int)abscissaV2, cucaoduZuobiao1[0], cucaoduZuobiao1[1], cucaoduZuobiao1[0], cucaodu1);
  1222. // 粗糙度2
  1223. SubFunction.LableHorizontal(image, (int)abscissaV6, cucaoduZuobiao2[0], cucaoduZuobiao2[1], cucaoduZuobiao2[0], cucaodu2);
  1224. }
  1225. public static void CaokongSicengZuo(string fileName)
  1226. {
  1227. // 一、预处理
  1228. // 读取图片
  1229. Mat image = new Mat(fileName, ImreadModes.Color);
  1230. //获取图片的长宽
  1231. int rows = image.Rows;
  1232. int cols = image.Cols;
  1233. // 转换为灰度图
  1234. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  1235. //获得蓝色,绿色,红色通道图片
  1236. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  1237. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  1238. // 二值化,获得目标区域
  1239. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  1240. // 闭运算,消除小孔
  1241. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  1242. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  1243. // 去亮光
  1244. Mat result = new Mat();
  1245. SubFunction.RemoveLightSiceng(imageContour, imageRed, out result, "left");
  1246. imageContour = result;
  1247. // 转成数组
  1248. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  1249. arrayContour = BasFunction.ConversionRange(arrayContour);
  1250. // 边缘检测
  1251. Mat imageOutlint = new Mat();
  1252. SubFunction.Sobel(imageContour, out imageOutlint);
  1253. int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint);
  1254. arrayOutline = BasFunction.ConversionRange(arrayOutline);
  1255. // 二、计算数据提取区域
  1256. // 对图片进行填充
  1257. Mat imageFill = new Mat();
  1258. SubFunction.Fill(imageContour, out imageFill);
  1259. // 计算数据提取区域
  1260. int[] dataArea = new int[2];
  1261. SubFunction.DataArea2(imageFill, out dataArea);
  1262. // 三、提取L1,L3,L4,L5, L6, L7, L8, L10
  1263. double meanOrdinateL1 = 0;
  1264. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]);
  1265. double meanOrdinateL3 = 0;
  1266. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1);
  1267. double meanOrdinateL4 = 0;
  1268. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3);
  1269. double meanOrdinateL5 = 0;
  1270. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4);
  1271. double meanOrdinateL6 = 0;
  1272. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5);
  1273. double meanOrdinateL7 = 0;
  1274. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL7, dataArea[0], dataArea[1], meanOrdinateL6);
  1275. double meanOrdinateL8 = 0;
  1276. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL8, dataArea[0], dataArea[1], meanOrdinateL7);
  1277. double meanOrdinateL10 = 0;
  1278. SubFunction.ExtractLines(arrayOutline, out meanOrdinateL10, dataArea[0], dataArea[1], meanOrdinateL8);
  1279. // 四、提取L2
  1280. double meanOrdinateL2 = 0;
  1281. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2);
  1282. // 五、提取L7
  1283. double meanOrdinateL9 = 0;
  1284. SubFunction.InsideLine(imageGreen, (int)meanOrdinateL8 + 10, (int)meanOrdinateL10 - 10, dataArea[0], dataArea[1], out meanOrdinateL10);
  1285. // 六、提取胶体线
  1286. Mat imageGlue1 = new Mat();
  1287. SubFunction.GlueArea(imageContour, imageRed, out imageGlue1, (int)meanOrdinateL3 + 10, (int)meanOrdinateL4 - 10, dataArea[0], dataArea[1]);
  1288. Mat imageGlue2 = new Mat();
  1289. SubFunction.GlueArea(imageContour, imageRed, out imageGlue2, (int)meanOrdinateL7 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1]);
  1290. // 转数组
  1291. int[,] arrayGlue1 = BasFunction.Mat2Array(imageGlue1);
  1292. arrayGlue1 = BasFunction.ConversionRange(arrayGlue1);
  1293. int[,] arrayGlue2 = BasFunction.Mat2Array(imageGlue2);
  1294. arrayGlue2 = BasFunction.ConversionRange(arrayGlue2);
  1295. // 提取胶体线
  1296. double meanOrdinateLG1 = 0;
  1297. SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL3 + 15, (int)meanOrdinateL4 - 15, dataArea[0], dataArea[1], out meanOrdinateLG1);
  1298. double meanOrdinateLG2 = 0;
  1299. SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL7 + 15, (int)meanOrdinateL8 - 15, dataArea[0], dataArea[1], out meanOrdinateLG2);
  1300. // 七、提取竖线V1、V2、V3、V4、V5、V6
  1301. double abscissaV1 = 0;
  1302. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateLG1);
  1303. double abscissaV2 = 0;
  1304. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateLG1, abscissaV1);
  1305. double abscissaV3 = 0;
  1306. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV3, (int)meanOrdinateL5, (int)meanOrdinateL6);
  1307. double abscissaV4 = 0;
  1308. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV4, (int)meanOrdinateL5, (int)meanOrdinateL6, abscissaV3);
  1309. double abscissaV5 = 0;
  1310. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV5, (int)meanOrdinateLG2, (int)meanOrdinateL8);
  1311. double abscissaV6 = 0;
  1312. SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV6, (int)meanOrdinateLG2, (int)meanOrdinateL8, abscissaV5);
  1313. // 八、计算粗糙度
  1314. int cucaodu1;
  1315. int[] cucaoduZuobiao1 = new int[2];
  1316. SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL3 + 60, (int)meanOrdinateL4 - 30, (int)abscissaV2, out cucaodu1, out cucaoduZuobiao1);
  1317. int cucaodu2;
  1318. int[] cucaoduZuobiao2 = new int[2];
  1319. SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL7 + 60, (int)meanOrdinateL8 - 30, (int)abscissaV6, out cucaodu2, out cucaoduZuobiao2);
  1320. // 九、计算数据
  1321. double upperMiantong = meanOrdinateL2 - meanOrdinateL1;
  1322. double upperJicaitong = meanOrdinateL3 - meanOrdinateL2;
  1323. double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1;
  1324. double lowerMiantong = meanOrdinateL10 - meanOrdinateL8;
  1325. double lowerJicaitong = meanOrdinateL9 - meanOrdinateL8;
  1326. double lowerMian_Jicaitong = meanOrdinateL10 - meanOrdinateL8;
  1327. double upperKongtong = abscissaV1 - abscissaV2;
  1328. double middleKongtong = abscissaV3 - abscissaV4;
  1329. double lowerKongtong = abscissaV5 - abscissaV6;
  1330. // 十、标记
  1331. int middle = (dataArea[0] + dataArea[1]) / 2;// 面铜+基材铜横坐标
  1332. int middle2 = (int)(meanOrdinateL3 + meanOrdinateLG1) / 2;// 孔铜1纵坐标
  1333. int middle3 = (int)(meanOrdinateL5 + meanOrdinateL6) / 2;// 孔铜2纵坐标
  1334. int middle4 = (int)(meanOrdinateLG2 + meanOrdinateL8) / 2;// 孔铜3纵坐标
  1335. // 上面铜
  1336. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong);
  1337. // 上基材铜
  1338. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong);
  1339. // 上面铜+基材铜
  1340. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong);
  1341. // 下面铜
  1342. SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong);
  1343. // 下基材铜
  1344. SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong);
  1345. // 下面铜+基材铜
  1346. SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong);
  1347. // 上孔铜
  1348. SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong);
  1349. // 中孔铜
  1350. SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, middleKongtong);
  1351. // 下孔铜
  1352. SubFunction.LableHorizontal(image, (int)abscissaV5, middle4, (int)abscissaV6, middle4, lowerKongtong);
  1353. // 粗糙度1
  1354. SubFunction.LableHorizontal(image, (int)abscissaV2, cucaoduZuobiao1[0], cucaoduZuobiao1[1], cucaoduZuobiao1[0], cucaodu1);
  1355. // 粗糙度2
  1356. SubFunction.LableHorizontal(image, (int)abscissaV6, cucaoduZuobiao2[0], cucaoduZuobiao2[1], cucaoduZuobiao2[0], cucaodu2);
  1357. }
  1358. public static void CaokongSicengZhong(string fileName)
  1359. {
  1360. // 一、预处理
  1361. // 读取图片
  1362. Mat image = new Mat(fileName, ImreadModes.Color);
  1363. //获取图片的长宽
  1364. int rows = image.Rows;
  1365. int cols = image.Cols;
  1366. // 转换为灰度图
  1367. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  1368. //获得蓝色,绿色,红色通道图片
  1369. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  1370. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  1371. // 重新修改比例调色
  1372. Mat imageNew = new Mat(imageRed.Size(), imageRed.Type());
  1373. imageNew = 0.9 * imageGreen + 0.1 * imageRed;
  1374. // 均值滤波
  1375. Mat imageFilter = new Mat();
  1376. Cv2.Blur(imageNew, imageFilter, new Size(5, 5));
  1377. // 二值化,获得目标区域
  1378. Mat imageContourText = imageFilter.Threshold(0, 255, ThresholdTypes.Otsu);// 用来计算消除亮光的边界
  1379. Mat imageContour = imageRed.Threshold(0, 255, ThresholdTypes.Otsu);
  1380. // 转成数组
  1381. int[,] arrayContourText = BasFunction.Mat2Array(imageContourText);
  1382. arrayContourText = BasFunction.ConversionRange(arrayContourText);
  1383. // 将中间亮光置0
  1384. int b2, b3;
  1385. SubFunction.SplitArea(arrayContourText, out b2, out b3);
  1386. Mat result = new Mat();
  1387. BasFunction.SetNumber(imageContour, out result, 0, rows, b2, b3, 0);// 亮光区域置0
  1388. imageContour = result;
  1389. // 闭运算,消除小孔
  1390. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  1391. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  1392. // 将原图分为两部分
  1393. int dividingLine = (b2 + b3) / 2;
  1394. Mat imageContour1 = imageContour;
  1395. Mat imageContour2 = imageContour;
  1396. for (int i = 0; i < rows; i++)
  1397. {
  1398. for (int j = 0; j < dividingLine; j++)
  1399. {
  1400. imageContour2.Set<int>(i, j, 0);
  1401. }
  1402. for (int k = dividingLine; k < cols; k++)
  1403. {
  1404. imageContour1.Set<int>(i, k, 0);
  1405. }
  1406. }
  1407. // 边缘检测
  1408. Mat imageOutline1;
  1409. Mat imageOutline2;
  1410. SubFunction.Sobel(imageContour1, out imageOutline1);
  1411. SubFunction.Sobel(imageContour2, out imageOutline2);
  1412. // 转成数组
  1413. int[,] arrayOutline1 = BasFunction.Mat2Array(imageOutline1);
  1414. arrayOutline1 = BasFunction.ConversionRange(arrayOutline1);
  1415. int[,] arrayOutline2 = BasFunction.Mat2Array(imageOutline2);
  1416. arrayOutline2 = BasFunction.ConversionRange(arrayOutline2);
  1417. // 计算图像1(左)
  1418. // 二、计算数据提取区域
  1419. // 对图片进行填充
  1420. Mat imageFill = new Mat();
  1421. SubFunction.Fill(imageContour1, out imageFill);
  1422. // 计算数据提取区域
  1423. int[] dataArea = new int[2];
  1424. SubFunction.DataArea2(imageFill, out dataArea);
  1425. // 三、提取L1,L3,L4,L5, L6, L7, L8, L10
  1426. double meanOrdinateLeft1 = 0;
  1427. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft1, dataArea[0], dataArea[1]);
  1428. double meanOrdinateLeft3 = 0;
  1429. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1);
  1430. double meanOrdinateLeft4 = 0;
  1431. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3);
  1432. double meanOrdinateLeft5 = 0;
  1433. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft5, dataArea[0], dataArea[1], meanOrdinateLeft4);
  1434. double meanOrdinateLeft6 = 0;
  1435. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5);
  1436. double meanOrdinateLeft7 = 0;
  1437. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft7, dataArea[0], dataArea[1], meanOrdinateLeft6);
  1438. double meanOrdinateLeft8 = 0;
  1439. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft8, dataArea[0], dataArea[1], meanOrdinateLeft7);
  1440. double meanOrdinateLeft10 = 0;
  1441. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft10, dataArea[0], dataArea[1], meanOrdinateLeft8);
  1442. // 四、提取L2
  1443. double meanOrdinateLeft2 = 0;
  1444. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2);
  1445. // 五、提取L7
  1446. double meanOrdinateLeft9 = 0;
  1447. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft8 + 10, (int)meanOrdinateLeft10 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft9);
  1448. // 六、提取胶体线
  1449. Mat imageGlueLeft1 = new Mat();
  1450. SubFunction.GlueArea(imageContour1, imageRed, out imageGlueLeft1, (int)meanOrdinateLeft3 + 10, (int)meanOrdinateLeft4 - 10, dataArea[0], dataArea[1]);
  1451. Mat imageGlueLeft2 = new Mat();
  1452. SubFunction.GlueArea(imageContour1, imageRed, out imageGlueLeft2, (int)meanOrdinateLeft7 + 10, (int)meanOrdinateLeft8 - 10, dataArea[0], dataArea[1]);
  1453. // 转数组
  1454. int[,] arrayGlueLeft1 = BasFunction.Mat2Array(imageGlueLeft1);
  1455. arrayGlueLeft1 = BasFunction.ConversionRange(arrayGlueLeft1);
  1456. int[,] arrayGlueLeft2 = BasFunction.Mat2Array(imageGlueLeft2);
  1457. arrayGlueLeft2 = BasFunction.ConversionRange(arrayGlueLeft2);
  1458. // 提取胶体线
  1459. double meanOrdinateLG1 = 0;
  1460. SubFunction.InsideLine(imageGlueLeft1, (int)meanOrdinateLeft3 + 15, (int)meanOrdinateLeft4 - 15, dataArea[0], dataArea[1], out meanOrdinateLG1);
  1461. double meanOrdinateLG2 = 0;
  1462. SubFunction.InsideLine(imageGlueLeft2, (int)meanOrdinateLeft7 + 15, (int)meanOrdinateLeft8 - 15, dataArea[0], dataArea[1], out meanOrdinateLG2);
  1463. // 七、提竖线V1,V2, V3, V4, V5, V6
  1464. double abscissaVLeft1 = 0;
  1465. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLG1);
  1466. double abscissaVLeft2 = 0;
  1467. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLG1, abscissaVLeft1);
  1468. double abscissaVLeft3 = 0;
  1469. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft3, (int)meanOrdinateLeft5, (int)meanOrdinateLeft6);
  1470. double abscissaVLeft4 = 0;
  1471. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft4, (int)meanOrdinateLeft5, (int)meanOrdinateLeft6, abscissaVLeft3);
  1472. double abscissaVLeft5 = 0;
  1473. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft5, (int)meanOrdinateLG2, (int)meanOrdinateLeft8);
  1474. double abscissaVLeft6 = 0;
  1475. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft6, (int)meanOrdinateLG2, (int)meanOrdinateLeft8, abscissaVLeft5);
  1476. // 八、计算粗糙度
  1477. int cucaoduLeft1 = 0;
  1478. int[] cucaoduZuobiaoLeft1 = new int[2];
  1479. SubFunction.Cucaodu(arrayOutline1, (int)meanOrdinateLeft3 + 60, (int)meanOrdinateLeft4 - 30, (int)abscissaVLeft2, out cucaoduLeft1, out cucaoduZuobiaoLeft1);
  1480. int cucaoduLeft2 = 0;
  1481. int[] cucaoduZuobiaoLeft2 = new int[2];
  1482. SubFunction.Cucaodu(arrayOutline1, (int)meanOrdinateLeft7 + 60, (int)meanOrdinateLeft8 - 30, (int)abscissaVLeft6, out cucaoduLeft2, out cucaoduZuobiaoLeft2);
  1483. // 计算图像2(右)
  1484. // 二、计算数据提取区域
  1485. // 对图片进行填充
  1486. Mat imageFill2 = new Mat();
  1487. SubFunction.Fill(imageContour2, out imageFill);
  1488. // 计算数据提取区域
  1489. int[] dataArea2 = new int[2];
  1490. SubFunction.DataArea2(imageFill2, out dataArea2);
  1491. // 三、提取L1,L3,L4,L5, L6, L7, L8, L10
  1492. double meanOrdinateRight1 = 0;
  1493. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight1, dataArea2[0], dataArea2[1]);
  1494. double meanOrdinateRight3 = 0;
  1495. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight3, dataArea2[0], dataArea2[1], meanOrdinateRight1);
  1496. double meanOrdinateRight4 = 0;
  1497. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight4, dataArea2[0], dataArea2[1], meanOrdinateRight3);
  1498. double meanOrdinateRight5 = 0;
  1499. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight5, dataArea2[0], dataArea2[1], meanOrdinateRight4);
  1500. double meanOrdinateRight6 = 0;
  1501. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight6, dataArea2[0], dataArea2[1], meanOrdinateRight5);
  1502. double meanOrdinateRight7 = 0;
  1503. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight7, dataArea2[0], dataArea2[1], meanOrdinateRight6);
  1504. double meanOrdinateRight8 = 0;
  1505. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight8, dataArea2[0], dataArea2[1], meanOrdinateRight7);
  1506. double meanOrdinateRight10 = 0;
  1507. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight10, dataArea2[0], dataArea2[1], meanOrdinateRight8);
  1508. // 四、提取L2
  1509. double meanOrdinateRight2 = 0;
  1510. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight2);
  1511. // 五、提取L9
  1512. double meanOrdinateRight9 = 0;
  1513. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight8 + 10, (int)meanOrdinateRight10 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight9);
  1514. // 六、提取胶体线
  1515. Mat imageGlueRight1 = new Mat();
  1516. SubFunction.GlueArea(imageContour2, imageRed, out imageGlueRight1, (int)meanOrdinateRight3 + 10, (int)meanOrdinateRight4 - 10, dataArea2[0], dataArea2[1]);
  1517. Mat imageGlueRight2 = new Mat();
  1518. SubFunction.GlueArea(imageContour2, imageRed, out imageGlueRight2, (int)meanOrdinateRight7 + 10, (int)meanOrdinateRight8 - 10, dataArea2[0], dataArea2[1]);
  1519. // 转数组
  1520. int[,] arrayGlueRight1 = BasFunction.Mat2Array(imageGlueRight1);
  1521. arrayGlueRight1 = BasFunction.ConversionRange(arrayGlueRight1);
  1522. int[,] arrayGlueRight2 = BasFunction.Mat2Array(imageGlueRight2);
  1523. arrayGlueRight2 = BasFunction.ConversionRange(arrayGlueRight2);
  1524. // 提取胶体线
  1525. double meanOrdinateRG1 = 0;
  1526. SubFunction.InsideLine(imageGlueRight1, (int)meanOrdinateRight3 + 15, (int)meanOrdinateRight4 - 15, dataArea2[0], dataArea2[1], out meanOrdinateRG1);
  1527. double meanOrdinateRG2 = 0;
  1528. SubFunction.InsideLine(imageGlueRight2, (int)meanOrdinateRight7 + 15, (int)meanOrdinateRight8 - 15, dataArea2[0], dataArea2[1], out meanOrdinateRG2);
  1529. // 七 、提竖线V1,V2, V3, V4, V5, V6
  1530. double abscissaVRight1 = 0;
  1531. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight1, (int)meanOrdinateRight3, (int)meanOrdinateRG1);
  1532. double abscissaVRight2 = 0;
  1533. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight2, (int)meanOrdinateRight3, (int)meanOrdinateRG1, abscissaVRight1);
  1534. double abscissaVRight3 = 0;
  1535. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight3, (int)meanOrdinateRight5, (int)meanOrdinateRight6);
  1536. double abscissaVRight4 = 0;
  1537. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight4, (int)meanOrdinateRight5, (int)meanOrdinateRight6, abscissaVRight3);
  1538. double abscissaVRight5 = 0;
  1539. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight5, (int)meanOrdinateRG2, (int)meanOrdinateRight8);
  1540. double abscissaVRight6 = 0;
  1541. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight6, (int)meanOrdinateRG2, (int)meanOrdinateRight8, abscissaVRight5);
  1542. // 八、计算粗糙度
  1543. int cucaoduRight1 = 0;
  1544. int[] cucaoduZuobiaoRight1 = new int[2];
  1545. SubFunction.Cucaodu(arrayOutline2, (int)meanOrdinateRight3 + 60, (int)meanOrdinateRight4 - 30, (int)abscissaVRight2, out cucaoduRight1, out cucaoduZuobiaoRight1);
  1546. int cucaoduRight2 = 0;
  1547. int[] cucaoduZuobiaoRight2 = new int[2];
  1548. SubFunction.Cucaodu(arrayOutline2, (int)meanOrdinateRight7 + 60, (int)meanOrdinateRight8 - 30, (int)abscissaVRight6, out cucaoduRight2, out cucaoduZuobiaoRight2);
  1549. // 九、数据计算
  1550. // 左
  1551. double leftUpperMiantong = meanOrdinateLeft2 - meanOrdinateLeft1;
  1552. double leftUpperJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2;
  1553. double leftUpperMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1;
  1554. double leftLowerMiantong = meanOrdinateLeft10 - meanOrdinateLeft9;
  1555. double leftLowerJicaitong = meanOrdinateLeft9 - meanOrdinateLeft8;
  1556. double leftLowerMian_Jicaitong = meanOrdinateLeft10 - meanOrdinateLeft8;
  1557. double leftKongtong1 = abscissaVLeft1 - abscissaVLeft2;
  1558. double leftKongtong2 = abscissaVLeft3 - abscissaVLeft4;
  1559. double leftKongtong3 = abscissaVLeft5 - abscissaVLeft6;
  1560. // 右
  1561. double rightUpperMiantong = meanOrdinateRight2 - meanOrdinateRight1;
  1562. double rightUpperJicaitong = meanOrdinateRight3 - meanOrdinateRight2;
  1563. double rightUpperMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1;
  1564. double rightLowerMiantong = meanOrdinateRight10 - meanOrdinateRight9;
  1565. double rightLowerJicaitong = meanOrdinateRight9 - meanOrdinateRight8;
  1566. double rightLowerMian_Jicaitong = meanOrdinateRight10 - meanOrdinateRight8;
  1567. double rightKongtong1 = abscissaVRight2 - abscissaVRight1;
  1568. double rightKongtong2 = abscissaVRight4 - abscissaVRight3;
  1569. double rightKongtong3 = abscissaVRight6 - abscissaVRight5;
  1570. double upperKongjing = abscissaVRight2 - abscissaVLeft2; ;
  1571. double lowerKongjing = abscissaVRight6 - abscissaVLeft6;
  1572. // 八、标记
  1573. int middleLeft = (dataArea[0] + dataArea[1]) / 2;// 左边面铜+基材铜横坐标
  1574. int middleLeft2 = (int)((meanOrdinateLeft3 + meanOrdinateLG1) / 2);// 左边孔铜1纵坐标
  1575. int middleLeft3 = (int)((meanOrdinateLeft5 + meanOrdinateLeft6) / 2);// 左边孔铜2纵坐标
  1576. int middleLeft4 = (int)((meanOrdinateLG2 + meanOrdinateLeft8) / 2);// 左边孔铜3纵坐标
  1577. int middleRight = (dataArea2[0] + dataArea2[1]) / 2;// 右边面铜+基材铜横坐标
  1578. int middleRight2 = (int)((meanOrdinateRight3 + meanOrdinateRG1) / 2);// 右边孔铜1纵坐标
  1579. int middleRight3 = (int)((meanOrdinateRight5 + meanOrdinateRight6) / 2);// 右边孔铜2纵坐标
  1580. int middleRight4 = (int)((meanOrdinateRG2 + meanOrdinateRight8) / 2);// 右边孔铜3纵坐标
  1581. // 图一标记(左)
  1582. // 上面铜
  1583. SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft1, middleLeft + 40, (int)meanOrdinateLeft2, leftUpperMiantong);
  1584. // 上基材铜
  1585. SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft2, middleLeft - 40, (int)meanOrdinateLeft3, leftUpperJicaitong);
  1586. // 上面铜+基材铜
  1587. SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft1, middleLeft, (int)meanOrdinateLeft3, leftUpperMian_Jicaitong);
  1588. // 下面铜
  1589. SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft9, middleLeft + 40, (int)meanOrdinateLeft10, leftLowerMiantong);
  1590. // 下基材铜
  1591. SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft8, middleLeft - 40, (int)meanOrdinateLeft9, leftLowerJicaitong);
  1592. // 下面铜+基材铜
  1593. SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft8, middleLeft, (int)meanOrdinateLeft10, leftLowerMian_Jicaitong);
  1594. // 孔铜
  1595. SubFunction.LableHorizontal(image, (int)abscissaVLeft2, middleLeft2, (int)abscissaVLeft1, middleLeft2, leftKongtong1);
  1596. SubFunction.LableHorizontal(image, (int)abscissaVLeft4, middleLeft3, (int)abscissaVLeft3, middleLeft3, leftKongtong2);
  1597. SubFunction.LableHorizontal(image, (int)abscissaVLeft6, middleLeft4, (int)abscissaVLeft5, middleLeft4, leftKongtong3);
  1598. // 图二标记(右)
  1599. // 上面铜
  1600. SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight1, middleRight + 40, (int)meanOrdinateRight2, rightUpperMiantong);
  1601. // 上基材铜
  1602. SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight2, middleRight - 40, (int)meanOrdinateRight3, rightUpperJicaitong);
  1603. // 上面铜+基材铜
  1604. SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight1, middleRight, (int)meanOrdinateRight3, rightUpperMian_Jicaitong);
  1605. // 下面铜
  1606. SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight9, middleRight + 40, (int)meanOrdinateRight10, rightLowerMiantong);
  1607. // 下基材铜
  1608. SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight8, middleRight - 40, (int)meanOrdinateRight9, rightLowerJicaitong);
  1609. // 下面铜+基材铜
  1610. SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight8, middleRight, (int)meanOrdinateRight10, rightLowerMian_Jicaitong);
  1611. // 孔铜
  1612. SubFunction.LableHorizontal(image, (int)abscissaVRight2, middleRight2, (int)abscissaVRight1, middleRight2, rightKongtong1);
  1613. SubFunction.LableHorizontal(image, (int)abscissaVRight4, middleRight3, (int)abscissaVRight3, middleRight3, rightKongtong2);
  1614. SubFunction.LableHorizontal(image, (int)abscissaVRight6, middleRight4, (int)abscissaVRight5, middleRight4, rightKongtong3);
  1615. // 上孔径
  1616. SubFunction.LableHorizontal(image, (int)abscissaVLeft2, (int)meanOrdinateLeft1, (int)abscissaVRight2, (int)meanOrdinateLeft1, upperKongjing);
  1617. // 下孔径
  1618. SubFunction.LableHorizontal(image, (int)abscissaVLeft6, (int)meanOrdinateLeft10, (int)abscissaVRight6, (int)meanOrdinateLeft10, lowerKongjing);
  1619. }
  1620. public static void CaokongShuangcengZhong(string fileName)
  1621. {
  1622. // 一、预处理
  1623. // 读取图片
  1624. Mat image = new Mat(fileName, ImreadModes.Color);
  1625. //获取图片的长宽
  1626. int rows = image.Rows;
  1627. int cols = image.Cols;
  1628. // 转换为灰度图
  1629. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  1630. //获得蓝色,绿色,红色通道图片
  1631. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  1632. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  1633. // 重新修改比例调色
  1634. Mat imageNew = new Mat(imageRed.Size(),imageRed.Type());
  1635. imageNew = 0.9 * imageGreen + 0.1 * imageRed;
  1636. // 均值滤波
  1637. Mat imageFilter = new Mat();
  1638. Cv2.Blur(imageNew, imageFilter, new Size(5, 5));
  1639. // 二值化,获得目标区域
  1640. Mat imageContourText = imageFilter.Threshold(0, 255, ThresholdTypes.Otsu);// 用来计算消除亮光的边界
  1641. Mat imageContour = imageRed.Threshold(0, 255, ThresholdTypes.Otsu);
  1642. // 转成数组
  1643. int[,] arrayContourText = BasFunction.Mat2Array(imageContourText);
  1644. arrayContourText = BasFunction.ConversionRange(arrayContourText);
  1645. // 将中间亮光置0
  1646. int b2, b3;
  1647. SubFunction.SplitArea(arrayContourText, out b2, out b3);
  1648. Mat result = new Mat();
  1649. BasFunction.SetNumber(imageContour, out result, 0, rows, b2, b3, 0);// 亮光区域置0
  1650. imageContour = result;
  1651. // 闭运算,消除小孔
  1652. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  1653. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  1654. // 将原图分为两部分
  1655. int dividingLine = (b2 + b3) / 2;
  1656. Mat imageContour1 = imageContour;
  1657. Mat imageContour2 = imageContour;
  1658. for (int i = 0; i < rows; i++)
  1659. {
  1660. for (int j = 0; j < dividingLine; j++)
  1661. {
  1662. imageContour2.Set<int>(i, j, 0);
  1663. }
  1664. for (int k = dividingLine; k < cols; k++)
  1665. {
  1666. imageContour1.Set<int>(i, k, 0);
  1667. }
  1668. }
  1669. // 边缘检测
  1670. Mat imageOutline1;
  1671. Mat imageOutline2;
  1672. SubFunction.Sobel(imageContour1, out imageOutline1);
  1673. SubFunction.Sobel(imageContour2, out imageOutline2);
  1674. // 转成数组
  1675. int[,] arrayOutline1 = BasFunction.Mat2Array(imageOutline1);
  1676. arrayOutline1 = BasFunction.ConversionRange(arrayOutline1);
  1677. int[,] arrayOutline2 = BasFunction.Mat2Array(imageOutline2);
  1678. arrayOutline2 = BasFunction.ConversionRange(arrayOutline2);
  1679. // 计算图像1(左)
  1680. // 二、计算数据提取区域
  1681. // 对图片进行填充
  1682. Mat imageFill = new Mat();
  1683. SubFunction.Fill(imageContour1, out imageFill);
  1684. // 计算数据提取区域
  1685. int[] dataArea = new int[2];
  1686. SubFunction.DataArea2(imageFill, out dataArea);
  1687. // 三、提取L1,L3,L4,L6
  1688. double meanOrdinateLeft1 = 0;
  1689. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft1, dataArea[0], dataArea[1]);
  1690. double meanOrdinateLeft3 = 0;
  1691. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1);
  1692. double meanOrdinateLeft4 = 0;
  1693. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3);
  1694. double meanOrdinateLeft6 = 0;
  1695. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft4);
  1696. // 四、提取L2
  1697. double meanOrdinateLeft2 = 0;
  1698. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2);
  1699. // 五、提取L5
  1700. double meanOrdinateLeft5 = 0;
  1701. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft4 + 10, (int)meanOrdinateLeft6 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft5);
  1702. // 六、提竖线V1,V2
  1703. double abscissaVLeft1 = 0;
  1704. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4);
  1705. double abscissaVLeft2 = 0;
  1706. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4, abscissaVLeft1);
  1707. // 计算图像2(右)
  1708. // 二、计算数据提取区域
  1709. // 对图片进行填充
  1710. Mat imageFill2 = new Mat();
  1711. SubFunction.Fill(imageContour2, out imageFill);
  1712. // 计算数据提取区域
  1713. int[] dataArea2 = new int[2];
  1714. SubFunction.DataArea2(imageFill2, out dataArea2);
  1715. // 三、提取L1,L3,L4,L6
  1716. double meanOrdinateRight1 = 0;
  1717. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight1, dataArea2[0], dataArea2[1]);
  1718. double meanOrdinateRight3 = 0;
  1719. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight3, dataArea2[0], dataArea2[1], meanOrdinateRight1);
  1720. double meanOrdinateRight4 = 0;
  1721. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight4, dataArea2[0], dataArea2[1], meanOrdinateRight3);
  1722. double meanOrdinateRight6 = 0;
  1723. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight6, dataArea2[0], dataArea2[1], meanOrdinateRight4);
  1724. // 四、提取L2
  1725. double meanOrdinateRight2 = 0;
  1726. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight2);
  1727. // 五、提取L5
  1728. double meanOrdinateRight5 = 0;
  1729. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight4 + 10, (int)meanOrdinateRight6 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight5);
  1730. // 六、提竖线V1,V2
  1731. double abscissaVRight1 = 0;
  1732. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight1, (int)meanOrdinateRight3, (int)meanOrdinateRight4);
  1733. double abscissaVRight2 = 0;
  1734. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight2, (int)meanOrdinateRight3, (int)meanOrdinateRight4, abscissaVRight1);
  1735. // 七、提取上孔径
  1736. double kongjingLeft1 = 0;
  1737. double kongjingLeft2 = 0;
  1738. double kongjingRight1 = 0;
  1739. double kongjingRight2 = 0;
  1740. SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLeft3 + 20);
  1741. SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLeft3 + 20, kongjingLeft1);
  1742. SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight1, (int)meanOrdinateRight3, (int)meanOrdinateRight3 + 20);
  1743. SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight2, (int)meanOrdinateRight3, (int)meanOrdinateRight3 + 20, kongjingRight1);
  1744. // 八、提取下孔径
  1745. double kongjingLeft3 = 0;
  1746. double kongjingLeft4 = 0;
  1747. double kongjingRight3 = 0;
  1748. double kongjingRight4 = 0;
  1749. SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft3, (int)meanOrdinateLeft4 - 20, (int)meanOrdinateLeft4);
  1750. SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft4, (int)meanOrdinateLeft4 - 20, (int)meanOrdinateLeft4, kongjingLeft3);
  1751. SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight3, (int)meanOrdinateRight4 - 20, (int)meanOrdinateRight4);
  1752. SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight4, (int)meanOrdinateRight4 - 20, (int)meanOrdinateRight4, kongjingRight3);
  1753. // 七、数据计算
  1754. // 左
  1755. double leftUpperMiantong = meanOrdinateLeft2 - meanOrdinateLeft1;
  1756. double leftUpperJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2;
  1757. double leftUpperMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1;
  1758. double leftLowerMiantong = meanOrdinateLeft6 - meanOrdinateLeft5;
  1759. double leftLowerJicaitong = meanOrdinateLeft5 - meanOrdinateLeft4;
  1760. double leftLowerMian_Jicaitong = meanOrdinateLeft6 - meanOrdinateLeft4;
  1761. double leftKongtong = abscissaVLeft1 - abscissaVLeft2;
  1762. // 右
  1763. double rightUpperMiantong = meanOrdinateRight2 - meanOrdinateRight1;
  1764. double rightUpperJicaitong = meanOrdinateRight3 - meanOrdinateRight2;
  1765. double rightUpperMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1;
  1766. double rightLowerMiantong = meanOrdinateRight6 - meanOrdinateRight5;
  1767. double rightLowerJicaitong = meanOrdinateRight5 - meanOrdinateRight4;
  1768. double rightLowerMian_Jicaitong = meanOrdinateRight6 - meanOrdinateRight4;
  1769. double rightKongtong = abscissaVRight2 - abscissaVRight1;
  1770. double upperKongjing = kongjingRight2 - kongjingLeft2;
  1771. double lowerKongjing = kongjingRight4 - kongjingLeft4;
  1772. // 八、标记
  1773. int middleLeft = (dataArea[0] + dataArea[1]) / 2;
  1774. int middleLeft2 = (int)((meanOrdinateLeft3 + meanOrdinateLeft4) / 2);
  1775. int middleRight = (dataArea2[0] + dataArea2[1]) / 2;
  1776. int middleRight2 = (int)((meanOrdinateRight3 + meanOrdinateRight4) / 2);
  1777. // 图一标记(左)
  1778. // 上面铜
  1779. SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft1, middleLeft + 40, (int)meanOrdinateLeft2, leftUpperMiantong);
  1780. // 上基材铜
  1781. SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft2, middleLeft - 40, (int)meanOrdinateLeft3, leftUpperJicaitong);
  1782. // 上面铜+基材铜
  1783. SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft1, middleLeft, (int)meanOrdinateLeft3, leftUpperMian_Jicaitong);
  1784. // 下面铜
  1785. SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft5, middleLeft + 40, (int)meanOrdinateLeft6, leftLowerMiantong);
  1786. // 下基材铜
  1787. SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft4, middleLeft - 40, (int)meanOrdinateLeft5, leftLowerJicaitong);
  1788. // 下面铜+基材铜
  1789. SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft4, middleLeft, (int)meanOrdinateLeft6, leftLowerMian_Jicaitong);
  1790. // 孔铜
  1791. SubFunction.LableHorizontal(image, (int)abscissaVLeft2, middleLeft2, (int)abscissaVLeft1, middleLeft2, leftKongtong);
  1792. // 图二标记(右)
  1793. // 上面铜
  1794. SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight1, middleRight + 40, (int)meanOrdinateRight2, rightUpperMiantong);
  1795. // 上基材铜
  1796. SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight2, middleRight - 40, (int)meanOrdinateRight3, rightUpperJicaitong);
  1797. // 上面铜+基材铜
  1798. SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight1, middleRight, (int)meanOrdinateRight3, rightUpperMian_Jicaitong);
  1799. // 下面铜
  1800. SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight5, middleRight + 40, (int)meanOrdinateRight6, rightLowerMiantong);
  1801. // 下基材铜
  1802. SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight4, middleRight - 40, (int)meanOrdinateRight5, rightLowerJicaitong);
  1803. // 下面铜+基材铜
  1804. SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight4, middleRight, (int)meanOrdinateRight6, rightLowerMian_Jicaitong);
  1805. // 孔铜
  1806. SubFunction.LableHorizontal(image, (int)abscissaVRight2, middleRight2, (int)abscissaVRight1, middleRight2, rightKongtong);
  1807. // 上孔径
  1808. SubFunction.LableHorizontal(image, (int)kongjingLeft2, (int)meanOrdinateLeft1, (int)kongjingRight2, (int)meanOrdinateLeft1, upperKongjing);
  1809. // 下孔径
  1810. SubFunction.LableHorizontal(image, (int)kongjingLeft4, (int)meanOrdinateLeft6, (int)kongjingRight4, (int)meanOrdinateLeft6, lowerKongjing);
  1811. }
  1812. public static void CaokongSancengZhong(string fileName)
  1813. {
  1814. // 一、预处理
  1815. // 读取图片
  1816. Mat image = new Mat(fileName, ImreadModes.Color);
  1817. //获取图片的长宽
  1818. int rows = image.Rows;
  1819. int cols = image.Cols;
  1820. // 转换为灰度图
  1821. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  1822. //获得蓝色,绿色,红色通道图片
  1823. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  1824. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  1825. // 重新修改比例调色
  1826. Mat imageNew = new Mat(imageRed.Size(), imageRed.Type());
  1827. imageNew = 0.9 * imageGreen + 0.1 * imageRed;
  1828. // 均值滤波
  1829. Mat imageFilter = new Mat();
  1830. Cv2.Blur(imageNew, imageFilter, new Size(5, 5));
  1831. // 二值化,获得目标区域
  1832. Mat imageContourText = imageFilter.Threshold(0, 255, ThresholdTypes.Otsu);// 用来计算消除亮光的边界
  1833. Mat imageContour = imageRed.Threshold(0, 255, ThresholdTypes.Otsu);
  1834. // 转成数组
  1835. int[,] arrayContourText = BasFunction.Mat2Array(imageContourText);
  1836. arrayContourText = BasFunction.ConversionRange(arrayContourText);
  1837. // 将中间亮光置0
  1838. int b2, b3;
  1839. SubFunction.SplitArea(arrayContourText, out b2, out b3);
  1840. Mat result = new Mat();
  1841. BasFunction.SetNumber(imageContour, out result, 0, rows, b2, b3, 0);// 亮光区域置0
  1842. imageContour = result;
  1843. // 闭运算,消除小孔
  1844. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  1845. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  1846. // 将原图分为两部分
  1847. int dividingLine = (b2 + b3) / 2;
  1848. Mat imageContour1 = imageContour;
  1849. Mat imageContour2 = imageContour;
  1850. for (int i = 0; i < rows; i++)
  1851. {
  1852. for (int j = 0; j < dividingLine; j++)
  1853. {
  1854. imageContour2.Set<int>(i, j, 0);
  1855. }
  1856. for (int k = dividingLine; k < cols; k++)
  1857. {
  1858. imageContour1.Set<int>(i, k, 0);
  1859. }
  1860. }
  1861. // 边缘检测
  1862. Mat imageOutline1;
  1863. Mat imageOutline2;
  1864. SubFunction.Sobel(imageContour1, out imageOutline1);
  1865. SubFunction.Sobel(imageContour2, out imageOutline2);
  1866. // 转成数组
  1867. int[,] arrayOutline1 = BasFunction.Mat2Array(imageOutline1);
  1868. arrayOutline1 = BasFunction.ConversionRange(arrayOutline1);
  1869. int[,] arrayOutline2 = BasFunction.Mat2Array(imageOutline2);
  1870. arrayOutline2 = BasFunction.ConversionRange(arrayOutline2);
  1871. // 计算图像1(左)
  1872. // 二、计算数据提取区域
  1873. // 对图片进行填充
  1874. Mat imageFill = new Mat();
  1875. SubFunction.Fill(imageContour1, out imageFill);
  1876. // 计算数据提取区域
  1877. int[] dataArea = new int[2];
  1878. SubFunction.DataArea2(imageFill, out dataArea);
  1879. // 三、提取L1,L3,L4,L5, L6, L8
  1880. double meanOrdinateLeft1 = 0;
  1881. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft1, dataArea[0], dataArea[1]);
  1882. double meanOrdinateLeft3 = 0;
  1883. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1);
  1884. double meanOrdinateLeft4 = 0;
  1885. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3);
  1886. double meanOrdinateLeft5 = 0;
  1887. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft5, dataArea[0], dataArea[1], meanOrdinateLeft4);
  1888. double meanOrdinateLeft6 = 0;
  1889. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5);
  1890. double meanOrdinateLeft8 = 0;
  1891. SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft8, dataArea[0], dataArea[1], meanOrdinateLeft6);
  1892. // 四、提取L2
  1893. double meanOrdinateLeft2 = 0;
  1894. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2);
  1895. // 五、提取L7
  1896. double meanOrdinateLeft7 = 0;
  1897. SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft6 + 10, (int)meanOrdinateLeft8 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft7);
  1898. // 六、提取胶体线
  1899. Mat imageGlue = new Mat();
  1900. SubFunction.GlueArea(imageContour1, imageRed, out imageGlue, (int)meanOrdinateLeft5 + 10, (int)meanOrdinateLeft6 - 10, dataArea[0], dataArea[1]);
  1901. // 转数组
  1902. int[,] arrayGlue = BasFunction.Mat2Array(imageGlue);
  1903. arrayGlue = BasFunction.ConversionRange(arrayGlue);
  1904. // 提取胶体线
  1905. double meanOrdinateLG = 0;
  1906. SubFunction.InsideLine(imageGlue, (int)meanOrdinateLeft5 + 15, (int)meanOrdinateLeft6 - 15, dataArea[0], dataArea[1], out meanOrdinateLG);
  1907. // 七、提竖线V1,V2, V3, V4
  1908. double abscissaVLeft1 = 0;
  1909. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4);
  1910. double abscissaVLeft2 = 0;
  1911. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4, abscissaVLeft1);
  1912. double abscissaVLeft3 = 0;
  1913. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft3, (int)meanOrdinateLG, (int)meanOrdinateLeft6);
  1914. double abscissaVLeft4 = 0;
  1915. SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft4, (int)meanOrdinateLG, (int)meanOrdinateLeft6, abscissaVLeft3);
  1916. // 八、计算粗糙度
  1917. int cucaoduLeft = 0;
  1918. int[] cucaoduZuobiaoLeft = new int[2];
  1919. SubFunction.Cucaodu(arrayOutline1, (int)meanOrdinateLeft5 + 60, (int)meanOrdinateLeft6 - 30, (int)abscissaVLeft4, out cucaoduLeft, out cucaoduZuobiaoLeft);
  1920. // 计算图像2(右)
  1921. // 二、计算数据提取区域
  1922. // 对图片进行填充
  1923. Mat imageFill2 = new Mat();
  1924. SubFunction.Fill(imageContour2, out imageFill);
  1925. // 计算数据提取区域
  1926. int[] dataArea2 = new int[2];
  1927. SubFunction.DataArea2(imageFill2, out dataArea2);
  1928. // 三、提取L1,L3,L4,L5, L6, L8
  1929. double meanOrdinateRight1 = 0;
  1930. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight1, dataArea2[0], dataArea2[1]);
  1931. double meanOrdinateRight3 = 0;
  1932. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight3, dataArea2[0], dataArea2[1], meanOrdinateRight1);
  1933. double meanOrdinateRight4 = 0;
  1934. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight4, dataArea2[0], dataArea2[1], meanOrdinateRight3);
  1935. double meanOrdinateRight5 = 0;
  1936. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight5, dataArea2[0], dataArea2[1], meanOrdinateRight4);
  1937. double meanOrdinateRight6 = 0;
  1938. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight6, dataArea2[0], dataArea2[1], meanOrdinateRight5);
  1939. double meanOrdinateRight8 = 0;
  1940. SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight8, dataArea2[0], dataArea2[1], meanOrdinateRight6);
  1941. // 四、提取L2
  1942. double meanOrdinateRight2 = 0;
  1943. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight2);
  1944. // 五、提取L5
  1945. double meanOrdinateRight7 = 0;
  1946. SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight6 + 10, (int)meanOrdinateRight8 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight7);
  1947. // 六、提取胶体线
  1948. Mat imageGlue2 = new Mat();
  1949. SubFunction.GlueArea(imageContour2, imageRed, out imageGlue2, (int)meanOrdinateRight5 + 10, (int)meanOrdinateRight6 - 10, dataArea2[0], dataArea2[1]);
  1950. // 转数组
  1951. int[,] arrayGlue2 = BasFunction.Mat2Array(imageGlue2);
  1952. arrayGlue2 = BasFunction.ConversionRange(arrayGlue2);
  1953. // 提取胶体线
  1954. double meanOrdinateRG = 0;
  1955. SubFunction.InsideLine(imageGlue, (int)meanOrdinateRight5 + 15, (int)meanOrdinateRight6 - 15, dataArea2[0], dataArea2[1], out meanOrdinateRG);
  1956. // 七 、提竖线V1,V2, V3, V4
  1957. double abscissaVRight1 = 0;
  1958. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight1, (int)meanOrdinateRight3, (int)meanOrdinateRight4);
  1959. double abscissaVRight2 = 0;
  1960. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight2, (int)meanOrdinateRight3, (int)meanOrdinateRight4, abscissaVRight1);
  1961. double abscissaVRight3 = 0;
  1962. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight3, (int)meanOrdinateRG, (int)meanOrdinateRight6);
  1963. double abscissaVRight4 = 0;
  1964. SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight4, (int)meanOrdinateRG, (int)meanOrdinateRight6, abscissaVRight3);
  1965. // 八、计算粗糙度
  1966. int cucaoduRight = 0;
  1967. int[] cucaoduZuobiaoRight = new int[2];
  1968. SubFunction.Cucaodu(arrayOutline2, (int)meanOrdinateRight5 + 60, (int)meanOrdinateRight6 - 30, (int)abscissaVRight4, out cucaoduRight, out cucaoduZuobiaoRight);
  1969. // 九、数据计算
  1970. // 左
  1971. double leftUpperMiantong = meanOrdinateLeft2 - meanOrdinateLeft1;
  1972. double leftUpperJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2;
  1973. double leftUpperMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1;
  1974. double leftLowerMiantong = meanOrdinateLeft6 - meanOrdinateLeft5;
  1975. double leftLowerJicaitong = meanOrdinateLeft5 - meanOrdinateLeft4;
  1976. double leftLowerMian_Jicaitong = meanOrdinateLeft6 - meanOrdinateLeft4;
  1977. double leftKongtong1 = abscissaVLeft1 - abscissaVLeft2;
  1978. double leftKongtong2 = abscissaVLeft3 - abscissaVLeft4;
  1979. // 右
  1980. double rightUpperMiantong = meanOrdinateRight2 - meanOrdinateRight1;
  1981. double rightUpperJicaitong = meanOrdinateRight3 - meanOrdinateRight2;
  1982. double rightUpperMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1;
  1983. double rightLowerMiantong = meanOrdinateRight6 - meanOrdinateRight5;
  1984. double rightLowerJicaitong = meanOrdinateRight5 - meanOrdinateRight4;
  1985. double rightLowerMian_Jicaitong = meanOrdinateRight6 - meanOrdinateRight4;
  1986. double rightKongtong1 = abscissaVRight2 - abscissaVRight1;
  1987. double rightKongtong2 = abscissaVRight4 - abscissaVRight3;
  1988. double upperKongjing = abscissaVRight2 - abscissaVLeft2; ;
  1989. double lowerKongjing = abscissaVRight4 - abscissaVLeft4;
  1990. // 八、标记
  1991. int middleLeft = (dataArea[0] + dataArea[1]) / 2;// 左面铜+基材铜横坐标
  1992. int middleLeft2 = (int)((meanOrdinateLeft3 + meanOrdinateLeft4) / 2);// 左孔铜1纵坐标
  1993. int middleLeft3 = (int)((meanOrdinateLG + meanOrdinateLeft6) / 2);// 左孔铜2纵坐标
  1994. int middleRight = (dataArea2[0] + dataArea2[1]) / 2;// 右面铜+基材铜横坐标
  1995. int middleRight2 = (int)((meanOrdinateRight3 + meanOrdinateRight4) / 2);// 右孔铜1纵坐标
  1996. int middleRight3 = (int)((meanOrdinateRG + meanOrdinateRight6) / 2);// 右孔铜2纵坐标
  1997. // 图一标记(左)
  1998. // 上面铜
  1999. SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft1, middleLeft + 40, (int)meanOrdinateLeft2, leftUpperMiantong);
  2000. // 上基材铜
  2001. SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft2, middleLeft - 40, (int)meanOrdinateLeft3, leftUpperJicaitong);
  2002. // 上面铜+基材铜
  2003. SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft1, middleLeft, (int)meanOrdinateLeft3, leftUpperMian_Jicaitong);
  2004. // 下面铜
  2005. SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft5, middleLeft + 40, (int)meanOrdinateLeft6, leftLowerMiantong);
  2006. // 下基材铜
  2007. SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft4, middleLeft - 40, (int)meanOrdinateLeft5, leftLowerJicaitong);
  2008. // 下面铜+基材铜
  2009. SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft4, middleLeft, (int)meanOrdinateLeft6, leftLowerMian_Jicaitong);
  2010. // 孔铜
  2011. SubFunction.LableHorizontal(image, (int)abscissaVLeft2, middleLeft2, (int)abscissaVLeft1, middleLeft2, leftKongtong1);
  2012. SubFunction.LableHorizontal(image, (int)abscissaVLeft4, middleLeft3, (int)abscissaVLeft3, middleLeft3, leftKongtong2);
  2013. // 图二标记(右)
  2014. // 上面铜
  2015. SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight1, middleRight + 40, (int)meanOrdinateRight2, rightUpperMiantong);
  2016. // 上基材铜
  2017. SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight2, middleRight - 40, (int)meanOrdinateRight3, rightUpperJicaitong);
  2018. // 上面铜+基材铜
  2019. SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight1, middleRight, (int)meanOrdinateRight3, rightUpperMian_Jicaitong);
  2020. // 下面铜
  2021. SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight5, middleRight + 40, (int)meanOrdinateRight6, rightLowerMiantong);
  2022. // 下基材铜
  2023. SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight4, middleRight - 40, (int)meanOrdinateRight5, rightLowerJicaitong);
  2024. // 下面铜+基材铜
  2025. SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight4, middleRight, (int)meanOrdinateRight6, rightLowerMian_Jicaitong);
  2026. // 孔铜
  2027. SubFunction.LableHorizontal(image, (int)abscissaVRight2, middleRight2, (int)abscissaVRight1, middleRight2, rightKongtong1);
  2028. SubFunction.LableHorizontal(image, (int)abscissaVRight4, middleRight3, (int)abscissaVRight3, middleRight3, rightKongtong2);
  2029. // 上孔径
  2030. SubFunction.LableHorizontal(image, (int)abscissaVLeft2, (int)meanOrdinateLeft1, (int)abscissaVRight2, (int)meanOrdinateLeft1, upperKongjing);
  2031. // 下孔径
  2032. SubFunction.LableHorizontal(image, (int)abscissaVLeft4, (int)meanOrdinateLeft6, (int)abscissaVRight4, (int)meanOrdinateLeft6, lowerKongjing);
  2033. }
  2034. public static void ShikeyinziDanceng(string fileName)
  2035. {
  2036. // 一、预处理
  2037. // 读取图片
  2038. Mat image = new Mat(fileName, ImreadModes.Color);
  2039. //获取图片的长宽
  2040. int rows = image.Rows;
  2041. int cols = image.Cols;
  2042. // 转换为灰度图
  2043. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  2044. //获得蓝色,绿色,红色通道图片
  2045. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  2046. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  2047. // 二值化,获得目标区域
  2048. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  2049. // 闭运算,消除小孔
  2050. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  2051. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  2052. // 转成数组
  2053. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  2054. arrayContour = BasFunction.ConversionRange(arrayContour);
  2055. // 选定检测区域
  2056. int[] dataArea = new int[4];
  2057. SubFunction.SKYZDataArea(imageContour, out dataArea);
  2058. // 截取检测区域
  2059. int[,] arrayData = BasFunction.InterceptArray(arrayContour, dataArea[0], dataArea[1], dataArea[2], dataArea[3]);
  2060. // 计算上横线位置
  2061. int[] upperX = new int[2];
  2062. SubFunction.UpperLine(arrayData, dataArea, out upperX);
  2063. // 计算上、下顶点坐标
  2064. int upperY;
  2065. int lowerY;
  2066. SubFunction.LowerLine(arrayData,(dataArea[3]-dataArea[2])/2, out upperY,out lowerY);
  2067. // 计算数据
  2068. int shangfu = upperX[1] - upperX[0];
  2069. int xiafu = dataArea[3] - dataArea[2];
  2070. int tonghou = lowerY - upperY;
  2071. // 标记
  2072. // 上幅
  2073. SubFunction.LableHorizontal(image, upperX[0]+dataArea[2], upperY+dataArea[0] - 10, upperX[1] + dataArea[2], upperY + dataArea[0] - 10, shangfu);
  2074. // 下幅
  2075. SubFunction.LableHorizontal(image, dataArea[2], lowerY + dataArea[0] + 10, dataArea[3], lowerY + dataArea[0] + 10, xiafu);
  2076. // 铜厚
  2077. int middle = (upperX[0] + upperX[1]) / 2;
  2078. SubFunction.LabelVertical(image, middle + dataArea[2], upperY + dataArea[0], middle + dataArea[2], lowerY + dataArea[0], tonghou);
  2079. // 保存
  2080. Cv2.ImWrite(@"D:\蚀刻因子单层.jpg",image);
  2081. // 显示
  2082. new Window("demo1", WindowMode.Normal, image);
  2083. Cv2.WaitKey(0);
  2084. }
  2085. public static void ShikeyinziShuangceng(string fileName)
  2086. {
  2087. // 一、预处理
  2088. // 读取图片
  2089. Mat image = new Mat(fileName, ImreadModes.Color);
  2090. //获取图片的长宽
  2091. int rows = image.Rows;
  2092. int cols = image.Cols;
  2093. // 转换为灰度图
  2094. Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY);
  2095. //获得蓝色,绿色,红色通道图片
  2096. Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type());
  2097. SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed);
  2098. // 二值化,获得目标区域
  2099. Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu);
  2100. // 闭运算,消除小孔
  2101. Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
  2102. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
  2103. // 开运算,去除小面积
  2104. Mat se2 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
  2105. Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Open, se2);
  2106. // 转成数组
  2107. int[,] arrayContour = BasFunction.Mat2Array(imageContour);
  2108. arrayContour = BasFunction.ConversionRange(arrayContour);
  2109. // 选定检测区域
  2110. int[] dataArea = new int[4];
  2111. SubFunction.SKYZDataArea(imageContour, out dataArea);
  2112. // 截取检测区域
  2113. int[,] arrayData = BasFunction.InterceptArray(arrayContour, dataArea[0], dataArea[1], dataArea[2], dataArea[3]);
  2114. // 计算上横线位置
  2115. int[] upperX = new int[2];
  2116. SubFunction.UpperLine(arrayData, dataArea, out upperX);
  2117. // 计算上、下顶点坐标
  2118. int upperY;
  2119. int lowerY;
  2120. SubFunction.LowerLine(arrayData,100, out upperY, out lowerY);
  2121. // 提取内部线
  2122. double insideY = 0;
  2123. SubFunction.InsideLine(imageGreen, upperY + 30+dataArea[0], lowerY - 50+dataArea[0], dataArea[2]+20, dataArea[3]-20, out insideY);
  2124. // 计算数据
  2125. int shangfu = upperX[1] - upperX[0];
  2126. int xiafu = dataArea[3] - dataArea[2];
  2127. int tonghou = lowerY+dataArea[0] - (int)insideY;
  2128. int zonghou = lowerY - upperY;
  2129. // 标记
  2130. // 上幅
  2131. SubFunction.LableHorizontal(image, upperX[0]+dataArea[2], upperY - 10+dataArea[0], upperX[1] + dataArea[2], upperY - 10 + dataArea[0], shangfu);
  2132. // 下幅
  2133. SubFunction.LableHorizontal(image, dataArea[2], lowerY + 10 + dataArea[0], dataArea[3], lowerY + 10 + dataArea[0], xiafu);
  2134. // 总厚
  2135. int middle = (upperX[0] + upperX[1]) / 2;
  2136. SubFunction.LabelVertical(image, dataArea[2]+100, upperY + dataArea[0], dataArea[2]+100, lowerY + dataArea[0], zonghou);
  2137. // 铜厚
  2138. SubFunction.LabelVertical(image, dataArea[3]-100, (int)insideY , dataArea[3]-100, lowerY + dataArea[0], tonghou);
  2139. // 保存
  2140. Cv2.ImWrite(@"D:\蚀刻因子双层.jpg", image);
  2141. // 显示
  2142. new Window("demo1", WindowMode.Normal, image);
  2143. Cv2.WaitKey(0);
  2144. }
  2145. }
  2146. }