12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068 |
- using OpenCvSharp;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- namespace SmartCoalApplication.Base.CommTool
- {
- public class Tools
- {
- /// <summary>
- /// 阴影校正
- /// </summary>
- /// <param name="src"></param>
- /// <returns></returns>
- public static Mat ShadingCorrection(Mat src)
- {
- if (src.Channels() == 1)
- return src;
- Mat temp = null, Ag = null, A0 = null, Aglp = null, dst = null;
- try
- {
- src.ConvertTo(src, MatType.CV_32FC3);
- temp = src.CvtColor(ColorConversionCodes.BGR2YCrCb);
- Mat[] tempArr = temp.Split();
- Ag = new Mat();
- tempArr[0].CopyTo(Ag); ;
- A0 = new Mat();
- Ag.CopyTo(A0);
- Aglp = ImageSmoothIIR(Ag, 0.99);
- tempArr[0] = A0 - Aglp + Cv2.Mean(Aglp);
- dst = new Mat();
- Cv2.Merge(tempArr, dst);
- dst = dst.CvtColor(ColorConversionCodes.YCrCb2BGR);
- dst.ConvertTo(dst, MatType.CV_8UC3);
- dst.CopyTo(src);
- return src;
- }
- catch (Exception e)
- {
- throw e;
- }
- finally
- {
- if (temp != null) temp.Dispose();
- if (Ag != null) Ag.Dispose();
- if (A0 != null) A0.Dispose();
- if (Aglp != null) Aglp.Dispose();
- if (dst != null) dst.Dispose();
- GC.Collect();
- }
- }
- public static Mat ImageSmoothIIR(Mat I_OUT, double threshold)
- {
- int M = I_OUT.Height;
- int N = I_OUT.Width;
- for (int P = 1; P < M; P++)
- {
- I_OUT.Row[P] = threshold * 1.0f * (I_OUT.Row[P - 1] - I_OUT.Row[P]) + I_OUT.Row[P];
- }
- for (int P = M - 2; P > -1; P--)
- {
- I_OUT.Row[P] = threshold * 1.0f * (I_OUT.Row[P + 1] - I_OUT.Row[P]) + I_OUT.Row[P];
- }
- for (int L = 1; L < N; L++)
- {
- I_OUT.Col[L] = threshold * 1.0f * (I_OUT.Col[L - 1] - I_OUT.Col[L]) + I_OUT.Col[L];
- }
- for (int L = N - 2; L > -1; L--)
- {
- I_OUT.Col[L] = threshold * 1.0f * (I_OUT.Col[L + 1] - I_OUT.Col[L]) + I_OUT.Col[L];
- }
- return I_OUT;
- }
- #region 分水岭分割
- /** the following constants are used to set bits corresponding to pixel types */
- static byte MAXIMUM = (byte)1; // marks local maxima (irrespective of noise tolerance)
- static byte LISTED = (byte)2; // marks points currently in the list
- static byte PROCESSED = (byte)4; // marks points processed previously
- static byte MAX_AREA = (byte)8; // marks areas near a maximum, within the tolerance
- //static byte EQUAL = (byte)16; // marks contigous maximum points of equal level
- //static byte MAX_POINT = (byte)32; // marks a single point standing for a maximum
- static byte ELIMINATED = (byte)64; // marks maxima that have been eliminated before watershed
- /// <summary>
- /// 分水岭分割
- /// </summary>
- /// <param name="mat"></param>
- /// <param name="lists"></param>
- /// <returns></returns>
- public static Mat WatershedSegment(Mat Inmat, int a)
- {
- int width = Inmat.Width;
- int height = Inmat.Height;
- Mat distance_temp = new Mat();
- //Cv2.ImShow("Inmat", Inmat);
- Cv2.DistanceTransform(Inmat, distance_temp, DistanceTypes.L2, DistanceMaskSize.Precise);
- //Mat dst_temp = new Mat();
- //Cv2.Normalize(src_temp, dst_temp, 0, 255, NormTypes.MinMax);
- //Mat dst = new Mat();
- //dst_temp.ConvertTo(dst, MatType.CV_8UC1);
- //Cv2.ImShow("DistanceTransform", dst);
- //getSortedMaxPoints............
- BitMap2d ip = new BitMap2d(distance_temp);
- MaximunFinder maximunFinder = new MaximunFinder(ip);
- List<Int16DoubleWithValue> maxPoints = maximunFinder.FindMaxima();
- //AnalyzeAndMarkMaxima.............
- BitMap2d types = new BitMap2d(width, height, 0);
- float globalMin = float.MaxValue;
- float globalMax = float.MinValue;
- foreach (Int16DoubleWithValue item in maxPoints)
- {
- if (item.V < globalMin) globalMin = item.V;
- if (item.V > globalMax) globalMax = item.V;
- types.SetPixel(item.O, MAXIMUM);
- }
- int nMax = maxPoints.Count();
- int[] pList = new int[width * height]; //here we enter points starting from a maximum
- int[] dirOffset = new int[] { -width, -width + 1, +1, +width + 1, +width, +width - 1, -1, -width - 1 };
- float maxSortingError = (float)(1.1 * (Math.Sqrt(2) / 2));//sorted sequence may be inaccurate by this value
- float tolerance = (float)0.5;// 05;
- for (int iMax = nMax - 1; iMax >= 0; iMax--)
- { //process all maxima now, starting from the highest
- int offset0 = maxPoints[iMax].O;
- if (((byte)types.GetPixel(offset0) & PROCESSED) != 0) //this maximum has been reached from another one, skip it
- continue;
- float v0 = ip.GetPixel(offset0);
- Boolean sortingError = false;
- do
- {
- pList[0] = offset0;
- types.SetPixel(offset0, (byte)((byte)types.GetPixel(offset0) | LISTED)); //mark first point as equal height (to itself) and listed
- int listLen = 1; //number of elements in the list
- int listI = 0; //index of current element in the list
- sortingError = false;
- Boolean maxPossible = true; //it may be a true maximum
- do
- { //while neigbor list is not fully processed (to listLen)
- int offset = pList[listI];
- int x = offset % width;
- int y = offset / width;
- Boolean isInner = (y != 0 && y != height - 1) && (x != 0 && x != width - 1); //not necessary, but faster than isWithin
- for (int d = 0; d < 8; d++)
- { //analyze all neighbors (in 8 directions) at the same level
- int offset2 = offset + dirOffset[d];
- if ((isInner || isWithin(x, y, d, width, height)) && ((byte)types.GetPixel(offset2) & LISTED) == 0)
- {
- float v2 = ip.GetPixel(offset2);
- if (ip.GetPixel(offset2) <= 0)
- {
- continue; //ignore the background (non-particles)
- }
- if (((byte)types.GetPixel(offset2) & PROCESSED) != 0)
- {
- maxPossible = false; //we have reached a point processed previously, thus it is no maximum now
- break;
- }
- if (v2 > v0 + maxSortingError)
- {
- maxPossible = false; //we have reached a higher point, thus it is no maximum
- break;
- }
- else if (v2 >= v0 - tolerance)
- {
- if (v2 > v0)
- {
- sortingError = true;
- offset0 = offset2;
- v0 = v2;
- }
- pList[listLen] = offset2;
- listLen++; //we have found a new point within the tolerance
- types.SetPixel(offset2, (byte)((byte)types.GetPixel(offset2) | LISTED));
- }
- } // if isWithin & not LISTED
- } // for directions d
- listI++;
- } while (listI < listLen);
- if (sortingError)
- { //if x0,y0 was not the true maximum but we have reached a higher one
- for (listI = 0; listI < listLen; listI++)
- types.SetPixel(pList[listI], (byte)0); //reset all points encountered, then retry
- }
- else
- {
- //...............................................................................//
- int resetMask = ~LISTED;
- for (listI = 0; listI < listLen; listI++)
- {
- int offset = pList[listI];
- types.SetPixel(offset, (byte)((byte)types.GetPixel(offset) & resetMask)); //reset attributes no longer needed
- types.SetPixel(offset, (byte)((byte)types.GetPixel(offset) | PROCESSED)); //mark as processed
- if (maxPossible)
- {
- types.SetPixel(offset, (byte)((byte)types.GetPixel(offset) | MAX_AREA)); //reset attributes no longer needed
- }
- } // for listI
- }
- }
- while (sortingError);
- }// for all maxima iMax
- //if (nMax == 0) //no initial maxima at all? then consider all as 'within tolerance'
- // Arrays.fill(types, (byte)(PROCESSED | MAX_AREA));
- //makeUEPs:::
- double threshold = 0.5;
- //make8bit............
- double offset01 = globalMin - (globalMax - globalMin) * (1.0 / 253 / 2 - 1e-6); //everything above minValue should become >(byte)0
- double factor = 253 / (globalMax - globalMin);
- BitMap2d pixels = new BitMap2d(width, height, 0);
- int dataLen = height * width;
- for (int offset = 0; offset < dataLen; offset++)
- {
- float rawValue = ip.GetPixel(offset);
- if (rawValue < threshold) { }
- else if (((byte)types.GetPixel(offset) & MAX_AREA) != 0)
- pixels.SetPixel(offset, (byte)255); //prepare watershed by setting "true" maxima+surroundings to 255
- else
- {
- long v = (long)(1 + Math.Round((rawValue - offset01) * factor));
- if (v < 1) pixels.SetPixel(offset, (byte)1);
- else if (v <= 254) pixels.SetPixel(offset, (byte)(v & 255));
- else pixels.SetPixel(offset, (byte)254);
- }
- }
- //cleanupMaxima............
- for (int iMax = nMax - 1; iMax >= 0; iMax--)
- {
- int offset0 = maxPoints[iMax].O; //type cast gets lower 32 bits where pixel offset is encoded
- if (((int)types.GetPixel(offset0) & (MAX_AREA | ELIMINATED)) != 0) continue;
- int level = (byte)pixels.GetPixel(offset0) & 255;
- int loLevel = level + 1;
- pList[0] = offset0; //we start the list at the current maximum
- types.SetPixel(offset0, (byte)((byte)types.GetPixel(offset0) | LISTED)); //mark first point as listed
- int listLen = 1; //number of elements in the list
- int lastLen = 1;
- int listI = 0; //index of current element in the list
- Boolean saddleFound = false;
- while (!saddleFound && loLevel > 0)
- {
- loLevel--;
- lastLen = listLen; //remember end of list for previous level
- listI = 0; //in each level, start analyzing the neighbors of all pixels
- do
- { //for all pixels listed so far
- int offset = pList[listI];
- int x = offset % width;
- int y = offset / width;
- Boolean isInner = (y != 0 && y != height - 1) && (x != 0 && x != width - 1); //not necessary, but faster than isWithin
- for (int d = 0; d < 8; d++)
- { //analyze all neighbors (in 8 directions) at the same level
- int offset2 = offset + dirOffset[d];
- if ((isInner || isWithin(x, y, d, width, height)) && ((byte)types.GetPixel(offset2) & LISTED) == 0)
- {
- if (((byte)types.GetPixel(offset2) & MAX_AREA) != 0 || ((((byte)types.GetPixel(offset2) & ELIMINATED) != 0) && ((byte)pixels.GetPixel(offset2) & 255) >= loLevel))
- {
- saddleFound = true; //we have reached a point touching a "true" maximum...
- break; //...or a level not lower, but touching a "true" maximum
- }
- else if (((byte)pixels.GetPixel(offset2) & 255) >= loLevel && ((byte)types.GetPixel(offset2) & ELIMINATED) == 0)
- {
- pList[listLen] = offset2;
- listLen++; //we have found a new point to be processed
- types.SetPixel(offset2, (byte)((byte)types.GetPixel(offset2) | LISTED));
- }
- } // if isWithin & not LISTED
- } // for directions d
- if (saddleFound) break; //no reason to search any further
- listI++;
- } while (listI < listLen);
- } // while !levelFound && loLevel>=0
- for (listI = 0; listI < listLen; listI++) //reset attribute since we may come to this place again
- types.SetPixel(pList[listI], (byte)((byte)types.GetPixel(pList[listI]) & ~LISTED));
- for (listI = 0; listI < lastLen; listI++)
- { //for all points higher than the level of the saddle point
- int offset = pList[listI];
- pixels.SetPixel(offset, (byte)loLevel); //set pixel value to the level of the saddle point
- types.SetPixel(offset, (byte)((byte)types.GetPixel(offset) | ELIMINATED)); //mark as processed: there can't be a local maximum in this area
- }
- } // for all maxima iMax
- //watershedSegment
- int[] histogram = new int[256];
- for (int v1 = 0; v1 < 255; v1++)
- {
- histogram[v1] = 0;
- }
- for (int offset = 0; offset < dataLen; offset++)
- {
- int v1 = (byte)pixels.GetPixel(offset) & 255;
- if (v1 > 0 && v1 < 255)
- {
- histogram[v1]++;
- }
- }
- int arraySize = width * height - histogram[0] - histogram[255];
- int[] coordinates = new int[arraySize]; //from pixel coordinates, low bits x, high bits y
- int highestValue = 0;
- int maxBinSize = 0;
- int offset02 = 0;
- int[] levelStart = new int[256];
- for (int v1 = 1; v1 < 255; v1++)
- {
- levelStart[v1] = offset02;
- offset02 += histogram[v1];
- if (histogram[v1] > 0) highestValue = v1;
- if (histogram[v1] > maxBinSize) maxBinSize = histogram[v1];
- }
- int[] levelOffset = new int[highestValue + 1];
- for (int y = 0, i = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++, i++)
- {
- int v1 = (byte)pixels.GetPixel(i) & 255;
- if (v1 > 0 && v1 < 255)
- {
- offset02 = levelStart[v1] + levelOffset[v1];
- coordinates[offset02] = x + y * width;
- levelOffset[v1]++;
- }
- } //for x
- } //for y
- // Create an array of the points (pixel offsets) that we set to 255 in one pass.
- // If we remember this list we need not create a snapshot of the ImageProcessor.
- int[] setPointList = new int[Math.Min(maxBinSize, (width * height + 2) / 3)];
- // now do the segmentation, starting at the highest level and working down.
- // At each level, dilate the particle (set pixels to 255), constrained to pixels
- // whose values are at that level and also constrained (by the fateTable)
- // to prevent features from merging.
- int[] table = makeFateTable();
- //IJ.showStatus("Segmenting (Esc to cancel)");
- /*final */
- int[] directionSequence = new int[] { 7, 3, 1, 5, 0, 4, 2, 6 }; // diagonal directions first
- for (int level = highestValue; level >= 1; level--)
- {
- int remaining = histogram[level]; //number of points in the level that have not been processed
- int idle = 0;
- while (remaining > 0 && idle < 8)
- {
- int sumN = 0;
- int dIndex = 0;
- do
- { // expand each level in 8 directions
- int n = processLevel(directionSequence[dIndex % 8], pixels, table,
- levelStart[level], remaining, coordinates, setPointList, width, height);
- //IJ.log("level="+level+" direction="+directionSequence[dIndex%8]+" remain="+remaining+"-"+n);
- remaining -= n; // number of points processed
- sumN += n;
- if (n > 0) idle = 0; // nothing processed in this direction?
- dIndex++;
- } while (remaining > 0 && idle++ < 8);
- }
- if (remaining > 0 && level > 1)
- { // any pixels that we have not reached?
- int nextLevel = level; // find the next level to process
- do
- nextLevel--;
- while (nextLevel > 1 && histogram[nextLevel] == 0);
- // in principle we should add all unprocessed pixels of this level to the
- // tasklist of the next level. This would make it very slow for some images,
- // however. Thus we only add the pixels if they are at the border (of the
- // image or a thresholded area) and correct unprocessed pixels at the very
- // end by CleanupExtraLines
- if (nextLevel > 0)
- {
- int newNextLevelEnd = levelStart[nextLevel] + histogram[nextLevel];
- for (int i = 0, p = levelStart[level]; i < remaining; i++, p++)
- {
- int pOffset = coordinates[p];
- int x = pOffset % width;
- int y = pOffset / width;
- //if ((pixels[pOffset] & 255) == 255) IJ.log("ERROR");
- Boolean addToNext = false;
- if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
- addToNext = true; //image border
- else for (int d = 0; d < 8; d++)
- if (isWithin(x, y, d, width, height) && pixels.GetPixel(pOffset + dirOffset[d]) == 0)
- {
- addToNext = true; //border of area below threshold
- break;
- }
- if (addToNext)
- coordinates[newNextLevelEnd++] = pOffset;
- }
- //tasklist for the next level to process becomes longer by this:
- histogram[nextLevel] = newNextLevelEnd - levelStart[nextLevel];
- }
- }
- }
- System.Drawing.Color color = Color.Blue;
- Mat matPixels = OpenCvSharp.Extensions.BitmapConverter.ToMat(pixels.MakeBmp());
- for (int h = 0; h < matPixels.Height; h++)
- {
- for (int w = 0; w < matPixels.Width; w++)
- {
- if (matPixels.At<byte>(h, w) == 0)
- matPixels.Set<Vec4b>(h, w, new Vec4b(color.B, color.G, color.R, 255));
- else
- matPixels.Set<Vec4b>(h, w, new Vec4b(0, 0, 0, 0));
- }
- }
- return matPixels;
- }
- /** returns whether the neighbor in a given direction is within the image
- * NOTE: it is assumed that the pixel x,y itself is within the image!
- * Uses class variables width, height: dimensions of the image
- * @param x x-coordinate of the pixel that has a neighbor in the given direction
- * @param y y-coordinate of the pixel that has a neighbor in the given direction
- * @param direction the direction from the pixel towards the neighbor (see makeDirectionOffsets)
- * @return true if the neighbor is within the image (provided that x, y is within)
- */
- public static Boolean isWithin(int x, int y, int direction, int width, int height)
- {
- int xmax = width - 1;
- int ymax = height - 1;
- switch (direction)
- {
- case 0:
- return (y > 0);
- case 1:
- return (x < xmax && y > 0);
- case 2:
- return (x < xmax);
- case 3:
- return (x < xmax && y < ymax);
- case 4:
- return (y < ymax);
- case 5:
- return (x > 0 && y < ymax);
- case 6:
- return (x > 0);
- case 7:
- return (x > 0 && y > 0);
- }
- return false; //to make the compiler happy :-)
- } // isWithin
- /** dilate the UEP on one level by one pixel in the direction specified by step, i.e., set pixels to 255
- * @param pass gives direction of dilation, see makeFateTable
- * @param ip the EDM with the segmeted blobs successively getting set to 255
- * @param table The fateTable
- * @param levelStart offsets of the level in pixelPointers[]
- * @param levelNPoints number of points in the current level
- * @param pixelPointers[] list of pixel coordinates (x+y*width) sorted by level (in sequence of y, x within each level)
- * @param xCoordinates list of x Coorinates for the current level only (no offset levelStart)
- * @return number of pixels that have been changed
- */
- public static int processLevel(int pass, BitMap2d pixels, int[] fateTable,
- int levelStart, int levelNPoints, int[] coordinates, int[] setPointList, int width, int height)
- {
- int xmax = width - 1;
- int ymax = height - 1;
- //byte[] pixels = (byte[])ip.getPixels();
- ////byte[] pixels2 = (byte[])ip2.getPixels();
- int nChanged = 0;
- int nUnchanged = 0;
- for (int i = 0, p = levelStart; i < levelNPoints; i++, p++)
- {
- int offset = coordinates[p];
- int x = offset % width;
- int y = offset / width;
- int index = 0; //neighborhood pixel ocupation: index in fateTable
- if (y > 0 && ((byte)pixels.GetPixel(offset - width) & 255) == 255)
- index ^= 1;
- if (x < xmax && y > 0 && ((byte)pixels.GetPixel(offset - width + 1) & 255) == 255)
- index ^= 2;
- if (x < xmax && ((byte)pixels.GetPixel(offset + 1) & 255) == 255)
- index ^= 4;
- if (x < xmax && y < ymax && ((byte)pixels.GetPixel(offset + width + 1) & 255) == 255)
- index ^= 8;
- if (y < ymax && ((byte)pixels.GetPixel(offset + width) & 255) == 255)
- index ^= 16;
- if (x > 0 && y < ymax && ((byte)pixels.GetPixel(offset + width - 1) & 255) == 255)
- index ^= 32;
- if (x > 0 && ((byte)pixels.GetPixel(offset - 1) & 255) == 255)
- index ^= 64;
- if (x > 0 && y > 0 && ((byte)pixels.GetPixel(offset - width - 1) & 255) == 255)
- index ^= 128;
- int mask = 1 << pass;
- if ((fateTable[index] & mask) == mask)
- setPointList[nChanged++] = offset; //remember to set pixel to 255
- else
- coordinates[levelStart + (nUnchanged++)] = offset; //keep this pixel for future passes
- } // for pixel i
- //IJ.log("pass="+pass+", changed="+nChanged+" unchanged="+nUnchanged);
- for (int i = 0; i < nChanged; i++)
- pixels.SetPixel(setPointList[i], (byte)255);
- return nChanged;
- } //processLevel
- static public int[] makeFateTable()
- {
- int[] table = new int[256];
- Boolean[] isSet = new Boolean[8];
- for (int item = 0; item < 256; item++)
- { //dissect into pixels
- for (int i = 0, mask = 1; i < 8; i++)
- {
- isSet[i] = (item & mask) == mask;
- mask *= 2;
- }
- for (int i = 0, mask = 1; i < 8; i++)
- { //we dilate in the direction opposite to the direction of the existing neighbors
- if (isSet[(i + 4) % 8]) table[item] |= mask;
- mask *= 2;
- }
- for (int i = 0; i < 8; i += 2) //if side pixels are set, for counting transitions it is as good as if the adjacent edges were also set
- if (isSet[i])
- {
- isSet[(i + 1) % 8] = true;
- isSet[(i + 7) % 8] = true;
- }
- int transitions = 0;
- for (int i = 0; i < 8; i++)
- {
- if (isSet[i] != isSet[(i + 1) % 8])
- transitions++;
- }
- if (transitions >= 4)
- { //if neighbors contain more than one region, dilation ito this pixel is forbidden
- table[item] = 0;
- }
- else
- {
- }
- }
- return table;
- } // int[] makeFateTable
- /// <summary>
- /// 分水岭分割
- /// </summary>
- /// <param name="mat"></param>
- /// <param name="lists"></param>
- /// <returns></returns>
- public static Mat WatershedSegment(Mat Inmat)
- {
- //BGR
- Mat Src_3 = new Mat();// .Clone();
- Mat[] arr = new Mat[3];
- arr[0] = Inmat;
- arr[1] = Inmat;
- arr[2] = Inmat;
- Cv2.Merge(arr, Src_3);
- //二值图
- Mat mat_bw = GetBW(Inmat);
- //Cv2.ImShow("mat_bw00", mat_bw);
- Mat result = Oper_Deal(mat_bw, Src_3);
- return result;// temp;
- }
- private static Mat Oper_Deal(Mat ImIn, Mat src_3)
- {
- #region 距离变换
- Mat Im1 = new Mat(ImIn.Size(), ImIn.Type());
- //归一化
- Cv2.Normalize(ImIn, Im1, 0, 1, NormTypes.MinMax);
- Mat Im_dis = new Mat(ImIn.Size(), MatType.CV_32FC1);
- Cv2.DistanceTransform(ImIn, Im_dis, DistanceTypes.L2, DistanceMaskSize.Precise);
- Cv2.Normalize(Im_dis, Im_dis, 0, 1, NormTypes.MinMax);
- Mat conv = new Mat(Im_dis.Size(), MatType.CV_8UC1);
- Im_dis.ConvertTo(conv, MatType.CV_8UC1);
- Cv2.Threshold(conv, conv, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);
- #endregion
- #region 轮廓标记
- Mat dis_8U = conv;
- //提取标记
- OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchy;
- Cv2.FindContours(dis_8U, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
- #endregion
- #region 将标记存入markers,作分水岭注水点用
- var markers = new Mat(ImIn.Size(), MatType.CV_32SC1, Scalar.All(0));
- for (int i = 0; i < contours.Length; i++)
- {
- Cv2.DrawContours(markers, contours, i, Scalar.All(i + 1), 10, LineTypes.Link8, hierarchy);
- }
- #endregion
- Cv2.Watershed(src_3, markers);
- #region 分水岭结果图处理
- //连通域为1,线条为0
- var markers_ind = markers.GetGenericIndexer<int>();
- for (int i = 0; i < markers.Rows; i++)
- {
- for (int j = 0; j < markers.Cols; j++)
- {
- if (markers_ind[i, j] != -1)
- {
- markers_ind[i, j] = int.MaxValue;
- }
- else if (markers_ind[i, j] == -1)
- {
- markers_ind[i, j] = 0;
- }
- }
- }
- //结合初始二值图背景为0
- var ImIn_ind = ImIn.GetGenericIndexer<byte>();
- for (int i = 0; i < markers.Rows; i++)
- {
- for (int j = 0; j < markers.Cols; j++)
- {
- if (ImIn_ind[i, j] == 0)
- {
- markers_ind[i, j] = 0;
- }
- }
- }
- #endregion
- #region 连通域信息
- Mat water = new Mat(markers.Size(), MatType.CV_8UC1);
- markers.ConvertTo(water, MatType.CV_8UC1);
- var water_ind = water.GetGenericIndexer<byte>();
- Mat water_bw = new Mat();
- Cv2.Threshold(water, water_bw, 0, 255, ThresholdTypes.Otsu);
- //连通图的信息获取
- Mat labels = new Mat(); Mat stats = new Mat(); Mat centroids = new Mat();
- int num = Cv2.ConnectedComponentsWithStats(water_bw, labels, stats, centroids);
- #endregion
- #region
- Vec3b[] color = new Vec3b[num + 1];
- color[0] = new Vec3b(0, 0, 0);
- var stats_ind = stats.GetGenericIndexer<int>();
- Random rand = new Random();
- byte ranB = (byte)rand.Next(100, 255); byte ranG = (byte)rand.Next(100, 255); byte ranR = (byte)rand.Next(100, 255);
- for (int i = 1; i < num; i++)
- {
- color[i] = new Vec3b(ranB, ranG, ranR);
- int S = stats_ind[i, 4];
- if (S < 200)
- {
- color[i] = new Vec3b(0, 0, 0);
- }
- }
- #endregion
- #region mat填色
- Mat final = new Mat(water.Size(), MatType.CV_8UC3);
- for (int i = 0; i < final.Rows; i++)
- {
- for (int j = 0; j < final.Cols; j++)
- {
- int label = labels.Get<int>(i, j);
- final.Set<Vec3b>(i, j, color[label]);
- }
- }
- #endregion
- return final;
- }
- private static Mat GetBW(Mat Src)
- {
- //(最大类间方差)二值化
- //Mat result = Src.Threshold(109.242, 255, ThresholdTypes.Otsu);
- Mat result = Src.AdaptiveThreshold(255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 35, 5);
- //Cv2.ImShow("test", result); Cv2.WaitKey();
- return result;
- }
- public struct Int16DoubleWithValue : IComparable<Int16DoubleWithValue>
- {
- public int O;
- public float V;
- public Int16DoubleWithValue(int offset, float value)
- {
- O = offset;
- V = value;
- }
- public int CompareTo(Int16DoubleWithValue other)
- {
- return this.V.CompareTo(other.V);
- }
- }
- public class BitMap2d
- {
- public float[] data;
- public int width;
- public int height;
- /// <summary>
- /// 初始化操作对象
- /// </summary>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="v">初始值</param>
- public BitMap2d(int width, int height, float v)
- {
- this.width = width;
- this.height = height;
- data = new float[width * height];
- for (int i = 0; i < width * height; i++)
- data[i] = v;
- }
- /// <summary>
- /// 根据mat初始化
- /// </summary>
- /// <param name="mat">初始EDM对象</param>
- public unsafe BitMap2d(Mat mat)
- {
- this.width = mat.Width;
- this.height = mat.Height;
- data = new float[width * height];
- mat.ForEachAsFloat(FunctionForEachAsFloat);
- }
- private unsafe void FunctionForEachAsFloat(float* value, int* position)
- {
- data[position[0] * width + position[1]] = *value;
- }
- public void SetPixel(int x, int y, byte v)
- {
- data[x + y * width] = v;
- }
- public float GetPixel(int x, int y)
- {
- return data[x + y * width];
- }
- public void SetPixel(int offset, byte v)
- {
- data[offset] = v;
- }
- public float GetPixel(int offset)
- {
- return data[offset];
- }
- public System.Drawing.Bitmap MakeBmp()
- {
- float min = float.MaxValue;
- float max = float.MinValue;
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- float r = this.GetPixel(i, j);
- if (r > max)
- max = r;
- if (r < min)
- min = r;
- }
- }
- float delta = max - min;
- System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(this.width, this.height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- for (int i = 0; i < width; i++)
- {
- for (int j = 0; j < height; j++)
- {
- float r = this.GetPixel(i, j);
- int b = 255 - (int)(255 * (r - min) / delta);
- System.Drawing.Color c = System.Drawing.Color.FromArgb((byte)b, (byte)b, (byte)b);
- bmp.SetPixel(i, j, c);
- }
- }
- return bmp;
- }
- }
- public class MaximunFinder
- {
- BitMap2d bmp;
- int width;
- int height;
- public MaximunFinder(BitMap2d bmp)
- {
- this.bmp = bmp;
- this.width = bmp.width;
- this.height = bmp.height;
- }
- public List<Int16DoubleWithValue> FindMaxima()
- {
- List<Int16DoubleWithValue> list = new List<Int16DoubleWithValue>();
- int offset = 0;
- for (int j = 0; j < height; j++)
- {
- for (int i = 0; i < width; i++, offset++)
- {
- if (IsMaxima(i, j, offset))
- {
- list.Add(new Int16DoubleWithValue(offset, bmp.GetPixel(offset)));
- }
- }
- }
- list.Sort();
- return list;
- }
- private bool IsMaxima(int i, int j, int offset)
- {
- float v = bmp.GetPixel(offset);
- if (v == 0) return false;
- bool b1 = v >= bmp.GetPixel(Math.Max(0, i - 1), Math.Max(0, j - 1));
- bool b2 = v >= bmp.GetPixel(i, Math.Max(0, j - 1));
- bool b3 = v >= bmp.GetPixel(Math.Min(width - 1, i + 1), Math.Max(0, j - 1));
- bool b4 = v >= bmp.GetPixel(Math.Max(0, i - 1), j);
- bool b5 = v >= bmp.GetPixel(Math.Min(width - 1, i + 1), j);
- bool b6 = v >= bmp.GetPixel(Math.Max(0, i - 1), Math.Min(height - 1, j + 1));
- bool b7 = v >= bmp.GetPixel(i, Math.Min(height - 1, j + 1));
- bool b8 = v >= bmp.GetPixel(Math.Min(width - 1, i + 1), Math.Min(height - 1, j + 1));
- return b1 && b2 && b3 && b4 && b5 && b6 && b7 && b8 && (v > 0);
- }
- }
- #endregion
- //颜色集合,用于聚类
- public static OpenCvSharp.Scalar[] colorTab = {
- new OpenCvSharp.Scalar(0,0,255),
- new OpenCvSharp.Scalar(0,255,0),
- new OpenCvSharp.Scalar(255,0,0),
- new OpenCvSharp.Scalar(0,255,255),
- new OpenCvSharp.Scalar(255,0,255),
- new OpenCvSharp.Scalar(255,255,0),
- new OpenCvSharp.Scalar(127,127,0),
- new OpenCvSharp.Scalar(0,0,127)
- };
- /// <summary>
- /// 直方图平滑
- /// </summary>
- /// <param name="arr"></param>
- /// <param name="step"></param>
- /// <returns></returns>
- public static int[] Smooth(float[] arr, int step)
- {
- int start = step - step / 2;
- int end = 256 - step / 2;
- double temp = 0;
- int[] res = new int[256];
- for (int i = start; i < end; i++)
- {
- temp = 0;
- for (int j = 0 - step / 2; j < step / 2; j++)
- {
- temp += arr[i + j];
- }
- temp /= step;
- res[i] = (int)temp;
- }
- return res;
- }
- /// <summary>
- /// 寻找波峰
- /// </summary>
- /// <param name="hists_new"></param>
- /// <param name="leftValue"></param>
- /// <param name="rightValue"></param>
- /// <param name="mountainsList"></param>
- /// <param name="mountainsArrList"></param>
- /// <param name="mountainsArrListBackUp"></param>
- /// <param name="str"></param>
- /// <param name="smoothStep"></param>
- public static void FindTopAndBetween(int[] hists_new, int leftValue, int rightValue, List<int> mountainsList, List<int[]> mountainsArrList, List<int[]> mountainsArrListBackUp, List<string> str, int smoothStep)
- {
- //获得去除左右值的最高波峰
- int topValue = leftValue;
- for (int y = leftValue; y < rightValue; y++)
- {
- if (hists_new[y] > hists_new[topValue])
- {
- topValue = y;
- }
- }
- if (topValue == 10)
- {
- FindTopAndBetween(hists_new, 11, rightValue, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- return;
- }
- mountainsList.Add(topValue);
- //获得波峰左右的波谷
- int leftTrough = topValue;
- int leftTroughBackUp = 0;
- //从波峰点向左侧找波谷点
- for (int y = topValue - 1; y > leftValue; y--)
- {
- if (hists_new[y] > 0 && hists_new[y] <= hists_new[leftTrough])
- {
- leftTrough = y;
- }
- else
- {
- break;
- }
- }
- //微调
- if (smoothStep > 2)
- {
- for (int y = leftTrough + 1; y < topValue; y++)
- {
- if (hists_new[y] == hists_new[leftTrough])// || hists_new[y] < hists_new[topValue] / 10)
- {
- leftTroughBackUp = y;
- }
- }
- }
- if (leftTroughBackUp == 0) leftTroughBackUp = leftTrough;
- int rightTrough = topValue;
- int rightTroughBackUp = 0;
- //从波峰点向右侧找波谷点
- for (int y = topValue + 1; y < rightValue; y++)
- {
- if (hists_new[y] > 0 && hists_new[y] <= hists_new[rightTrough])
- {
- rightTrough = y;
- }
- else
- {
- break;
- }
- }
- //微调
- if (smoothStep > 2)
- {
- for (int y = rightTrough - 1; y > topValue; y--)
- {
- if (hists_new[y] == hists_new[rightTrough])// || hists_new[y] < hists_new[topValue] / 10)
- {
- rightTroughBackUp = y;
- }
- }
- }
- if (rightTroughBackUp == 0) rightTroughBackUp = rightTrough;
- int[] arr = new int[2];
- arr[0] = leftTroughBackUp;
- arr[1] = rightTroughBackUp;
- mountainsArrList.Add(arr);
- int[] arr1 = new int[2];
- arr1[0] = leftTroughBackUp > 0 ? leftTroughBackUp : leftTrough;
- arr1[1] = rightTroughBackUp > 0 ? rightTroughBackUp : rightTrough;
- mountainsArrListBackUp.Add(arr1);
- if (leftValue < leftTrough - 1)
- {
- if (!str.Contains(leftValue + "|" + leftTrough))
- {
- str.Add(leftValue + "|" + leftTrough);
- FindTopAndBetween(hists_new, leftValue, leftTrough, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- }
- }
- if (rightValue > rightTrough + 1)
- {
- if (!str.Contains(rightValue + "|" + rightTrough))
- {
- str.Add(rightValue + "|" + rightTrough);
- FindTopAndBetween(hists_new, rightTrough, rightValue, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- }
- }
- }
- public static void FindTopAndBetweenWithOutWT(int[] hists_new, int leftValue, int rightValue, List<int> mountainsList, List<int[]> mountainsArrList, List<int[]> mountainsArrListBackUp, List<string> str, int smoothStep)
- {
- //获得去除左右值的最高波峰
- int topValue = leftValue;
- for (int y = leftValue; y < rightValue; y++)
- {
- if (hists_new[y] > hists_new[topValue])
- {
- topValue = y;
- }
- }
- if (topValue == 10)
- {
- FindTopAndBetween(hists_new, 11, rightValue, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- return;
- }
- mountainsList.Add(topValue);
- //获得波峰左右的波谷
- int leftTrough = topValue;
- int leftTroughBackUp = 0;
- //从波峰点向左侧找波谷点
- for (int y = topValue - 1; y > leftValue; y--)
- {
- if (hists_new[y] > 0 && hists_new[y] <= hists_new[leftTrough])
- {
- leftTrough = y;
- }
- else
- {
- break;
- }
- }
- //微调
- //if (smoothStep >= 30)
- {
- for (int y = leftTrough + 1; y < topValue; y++)
- {
- if (hists_new[y] == hists_new[leftTrough] || hists_new[y] < hists_new[topValue] / 10)
- {
- leftTroughBackUp = y;
- }
- }
- }
- if (leftTroughBackUp == 0) leftTroughBackUp = leftTrough;
- int rightTrough = topValue;
- int rightTroughBackUp = 0;
- //从波峰点向右侧找波谷点
- for (int y = topValue + 1; y < rightValue; y++)
- {
- if (hists_new[y] > 0 && hists_new[y] <= hists_new[rightTrough])
- {
- rightTrough = y;
- }
- else
- {
- break;
- }
- }
- //微调
- //if (smoothStep >= 30)
- {
- for (int y = rightTrough - 1; y > topValue; y--)
- {
- if (hists_new[y] == hists_new[rightTrough] || hists_new[y] < hists_new[topValue] / 10)
- {
- rightTroughBackUp = y;
- }
- }
- }
- if (rightTroughBackUp == 0) rightTroughBackUp = rightTrough;
- int[] arr = new int[2];
- arr[0] = leftTroughBackUp;
- arr[1] = rightTroughBackUp;
- mountainsArrList.Add(arr);
- int[] arr1 = new int[2];
- arr1[0] = leftTroughBackUp > 0 ? leftTroughBackUp : leftTrough;
- arr1[1] = rightTroughBackUp > 0 ? rightTroughBackUp : rightTrough;
- mountainsArrListBackUp.Add(arr1);
- if (leftValue < leftTrough - 1)
- {
- if (!str.Contains(leftValue + "|" + leftTrough))
- {
- str.Add(leftValue + "|" + leftTrough);
- FindTopAndBetween(hists_new, leftValue, leftTrough, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- }
- }
- if (rightValue > rightTrough + 1)
- {
- if (!str.Contains(rightValue + "|" + rightTrough))
- {
- str.Add(rightValue + "|" + rightTrough);
- FindTopAndBetween(hists_new, rightTrough, rightValue, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- }
- }
- }
- public unsafe static double Entropy(Mat img)
- {
- // 将输入的矩阵为图像
- double[] temp = new double[256];
- // 清零
- for (int i = 0; i < 256; i++)
- {
- temp[i] = 0.0;
- }
- // 计算每个像素的累积值
- for (int m = 0; m < img.Rows; m++)
- {// 有效访问行列的方式
- byte* t = (byte*)img.Ptr(m);
- for (int n = 0; n < img.Cols; n++)
- {
- int i = t[n];
- temp[i] = temp[i] + 1;
- }
- }
- // 计算每个像素的概率
- for (int i = 0; i < 256; i++)
- {
- temp[i] = temp[i] / (img.Rows * img.Cols);
- }
- double result = 0;
- // 根据定义计算图像熵
- for (int i = 0; i < 256; i++)
- {
- if (temp[i] == 0.0)
- result = result;
- else
- result = result - temp[i] * (Math.Log(temp[i]) / Math.Log(2.0));
- }
- return result;
- }
- /// <summary>
- /// 计算图像的熵
- /// </summary>
- /// <param name="bmp"></param>
- /// <param name="w"></param>
- /// <param name="h"></param>
- /// <returns></returns>
- public static double GetEntropy(Bitmap bmp, int w, int h)
- {
- int g;
- double H = 0.0;
- int[] pix = new int[256];
- Array.Clear(pix, 0, 256);
- //获取各灰度值的像素个数
- for (int i = 0; i < h; i++)
- {
- for (int j = 0; j < w; j++)
- {
- Color c = bmp.GetPixel(j, i);
- g = (int)(0.299 * c.R + 0.587 * c.B + 0.114 * c.G);
- pix[g]++;
- }
- }
- //计算熵
- for (int i = 0; i < 256; i++)
- {
- if (pix[i] > 0)
- {
- H = H + pix[i] * Math.Log10(pix[i]);
- }
- }
- H = Math.Log10(w * h) / Math.Log10(2) - H / (w * h * Math.Log10(2));
- return H;
- }
- /// <summary>
- /// 计算占比
- /// </summary>
- /// <param name="max"></param>
- /// <param name="hists_new"></param>
- /// <param name="toplow"></param>
- /// <returns></returns>
- public static double GetAreaRatio(int max, int[] hists_new, int[] toplow)
- {
- int all = 0;
- int area = 0;
- for (int i = toplow[0]; i < toplow[1]; i++)
- {
- all += hists_new[i];
- if (i <= max + 10 && i >= max - 10)
- {
- area += hists_new[i];
- }
- }
- return area * 1d * 100 / all;
- }
- /// <summary>
- /// 计算阈值
- /// </summary>
- /// <param name="max">最大值</param>
- /// <param name="min">最小值</param>
- /// <param name="t">1左 2右</param>
- /// <param name="hists_new">直方图</param>
- /// <returns></returns>
- public static double GetTriangleThreshold(int leftv, int topv, int rightv, int t, int[] hists_new)
- {
- int left_bound = leftv, right_bound = rightv, max_ind = topv, max = hists_new[topv];
- int temp;
- bool isflipped = false;
- int i = 0, j = 0;
- int N = 256;
- // 如果最大值落在靠左侧这样就无法满足三角法求阈值,所以要检测是否最大值是否靠近左侧
- // 如果靠近左侧则通过翻转到右侧位置。
- if (max_ind - left_bound < right_bound - max_ind)//max_ind - left_bound < right_bound - max_ind
- {
- isflipped = true;
- i = 0;
- j = N - 1;
- while (i < j)
- {
- // 左右交换
- temp = hists_new[i]; hists_new[i] = hists_new[j]; hists_new[j] = temp;
- i++; j--;
- }
- left_bound = N - 1 - right_bound;
- max_ind = N - 1 - max_ind;
- }
- // 计算求得阈值
- double thresh = left_bound;
- double a, b, dist = 0, tempdist;
- a = max; b = left_bound - max_ind;
- for (i = left_bound + 1; i <= max_ind; i++)
- {
- // 计算距离 - 不需要真正计算
- tempdist = a * i + b * hists_new[i];
- if (tempdist > dist)
- {
- dist = tempdist;
- thresh = i;
- }
- }
- thresh--;
- if (isflipped)
- thresh = N - 1 - thresh;
- return thresh;
- }
- /// <summary>
- /// 计算K类均值的每个类的灰度均值,面积
- /// </summary>
- public static List<float> CalaKmeanMatMeans(OpenCvSharp.Mat origin, OpenCvSharp.Mat kmean, out List<int> nums)
- {
- OpenCvSharp.Mat gray = origin.CvtColor(OpenCvSharp.ColorConversionCodes.BGR2GRAY);
- //像素点个数
- List<int> points = new List<int>();
- points.Add(0);
- points.Add(0);
- points.Add(0);
- points.Add(0);
- points.Add(0);
- //像素点灰度值的和
- List<int> grays = new List<int>();
- grays.Add(0);
- grays.Add(0);
- grays.Add(0);
- grays.Add(0);
- grays.Add(0);
- new OpenCvSharp.Scalar(0, 0, 255);
- new OpenCvSharp.Scalar(0, 255, 0);
- new OpenCvSharp.Scalar(255, 0, 0);
- new OpenCvSharp.Scalar(0, 255, 255);
- new OpenCvSharp.Scalar(255, 0, 255);
- for (int h = 0; h < kmean.Height; h++)
- {
- for (int w = 0; w < kmean.Width; w++)
- {
- OpenCvSharp.Vec3b vec3B = kmean.At<OpenCvSharp.Vec3b>(h, w);
- if (vec3B.Item0 == 0 && vec3B.Item1 == 0 && vec3B.Item2 == 255)
- {
- points[0] += 1;
- grays[0] += gray.At<byte>(h, w);
- }
- else if (vec3B.Item0 == 0 && vec3B.Item1 == 255 && vec3B.Item2 == 0)
- {
- points[1] += 1;
- grays[1] += gray.At<byte>(h, w);
- }
- else if (vec3B.Item0 == 255 && vec3B.Item1 == 0 && vec3B.Item2 == 0)
- {
- points[2] += 1;
- grays[2] += gray.At<byte>(h, w);
- }
- else if (vec3B.Item0 == 0 && vec3B.Item1 == 255 && vec3B.Item2 == 255)
- {
- points[3] += 1;
- grays[3] += gray.At<byte>(h, w);
- }
- else if (vec3B.Item0 == 255 && vec3B.Item1 == 0 && vec3B.Item2 == 255)
- {
- points[4] += 1;
- grays[4] += gray.At<byte>(h, w);
- }
- }
- }
- nums = points;
- List<float> vs = new List<float>();
- for (int i = 0; i < 5; i++)
- {
- vs.Add(grays[i] * 1f / points[i]);
- }
- return vs;
- }
- /// <summary>
- /// 判断点a和点b是否颜色一样
- /// </summary>
- /// <param name="v"></param>
- /// <param name="b"></param>
- /// <returns></returns>
- public static bool AdjustNearColor(Vec3b v, Scalar b)
- {
- if (v.Item0 == b.Val0 && v.Item1 == b.Val1 && v.Item2 == b.Val2)
- return true;
- else
- return false;
- }
- public static bool AdjustNearBy(Vec3b v, Vec3b b)
- {
- if (b.Item0 == 0 && b.Item1 == 0 && b.Item2 == 0)
- {
- return false;
- }
- else
- {
- if (v.Item0 != b.Item0 || v.Item1 != b.Item1 || v.Item2 != b.Item2)
- return true;
- else
- return false;
- }
- }
- public static void FindTopAndBetweenWithOutWT123(int[] hists_new, int leftValue, int rightValue, List<int> mountainsList, List<int[]> mountainsArrList, List<int[]> mountainsArrListBackUp, List<string> str, int smoothStep)
- {
- //获得去除左右值的最高波峰
- int topValue = leftValue;
- for (int y = leftValue; y < rightValue; y++)
- {
- if (hists_new[y] > hists_new[topValue])
- {
- topValue = y;
- }
- }
- if (topValue == 0 || topValue == leftValue || topValue == rightValue)
- return;
- mountainsList.Add(topValue);
- //获得波峰左右的波谷
- int leftTrough = topValue;
- int leftTroughBackUp = 0;
- //从波峰点向左侧找波谷点
- for (int y = topValue - 1; y > leftValue; y--)
- {
- if (hists_new[y] >= 0 && hists_new[y] <= hists_new[leftTrough])
- {
- leftTrough = y;
- }
- else
- {
- break;
- }
- }
- //微调
- //if (smoothStep >= 30)
- {
- for (int y = leftTrough + 1; y < topValue; y++)
- {
- if (hists_new[y] == hists_new[leftTrough])// || hists_new[y] < hists_new[topValue] / 10
- {
- leftTroughBackUp = y;
- }
- }
- }
- if (leftTroughBackUp == 0) leftTroughBackUp = leftTrough;
- int rightTrough = topValue;
- int rightTroughBackUp = 0;
- //从波峰点向右侧找波谷点
- for (int y = topValue + 1; y < rightValue; y++)
- {
- if (hists_new[y] >= 0 && hists_new[y] <= hists_new[rightTrough])
- {
- rightTrough = y;
- }
- else
- {
- break;
- }
- }
- //微调
- //if (smoothStep >= 30)
- {
- for (int y = rightTrough - 1; y > topValue; y--)
- {
- if (hists_new[y] == hists_new[rightTrough])// || hists_new[y] < hists_new[topValue] / 10
- {
- rightTroughBackUp = y;
- }
- }
- }
- if (rightTroughBackUp == 0) rightTroughBackUp = rightTrough;
- int[] arr = new int[2];
- arr[0] = leftTroughBackUp;
- arr[1] = rightTroughBackUp;
- mountainsArrList.Add(arr);
- int[] arr1 = new int[2];
- arr1[0] = leftTroughBackUp > 0 ? leftTroughBackUp : leftTrough;
- arr1[1] = rightTroughBackUp > 0 ? rightTroughBackUp : rightTrough;
- mountainsArrListBackUp.Add(arr1);
- if (leftValue < leftTrough - 1)
- {
- if (!str.Contains(leftValue + "|" + leftTrough))
- {
- str.Add(leftValue + "|" + leftTrough);
- FindTopAndBetweenWithOutWT123(hists_new, leftValue, leftTrough, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- }
- }
- if (rightValue > rightTrough + 1)
- {
- if (!str.Contains(rightValue + "|" + rightTrough))
- {
- str.Add(rightValue + "|" + rightTrough);
- FindTopAndBetweenWithOutWT123(hists_new, rightTrough, rightValue, mountainsList, mountainsArrList, mountainsArrListBackUp, str, smoothStep);
- }
- }
- }
- public static float areaRatio(int[] hists_new, int[] se)
- {
- int sum = hists_new.Sum();
- int sum1 = 0;
- for (int i = se[0]; i < se[1]; i++)
- {
- sum1 += hists_new[i];
- }
- return (sum1 * 1f / sum) * 100;
- }
- /// <summary>
- /// 测试用标尺
- /// </summary>
- public static double bc = 5.3191 / 1000;
- /// <summary>
- /// 获取两点之间的距离
- /// </summary>
- /// <param name="pointO"></param>
- /// <param name="pointA"></param>
- /// <returns></returns>
- public static double getDistance(OpenCvSharp.Point pointO, OpenCvSharp.Point pointA)
- {
- double distance;
- distance = Math.Pow((pointO.X - pointA.X), 2) + Math.Pow((pointO.Y - pointA.Y), 2);
- distance = Math.Sqrt(distance);
- return distance;
- }
- /// <summary>
- /// 获取点到直线的距离
- /// </summary>
- /// <param name="pointP"></param>
- /// <param name="pointA"></param>
- /// <param name="pointB"></param>
- /// <returns></returns>
- public static float getDist_P2L(OpenCvSharp.Point pointP, OpenCvSharp.Point pointA, OpenCvSharp.Point pointB)
- {
- int A = 0, B = 0, C = 0;
- A = pointA.Y - pointB.Y;
- B = pointB.X - pointA.X;
- C = pointA.X * pointB.Y - pointA.Y * pointB.X;
- float distance = 0;
- distance = ((float)Math.Abs(A * pointP.X + B * pointP.Y + C)) / ((float)Math.Sqrt(A * A + B * B));
- return distance;
- }
- /// <summary>
- /// 原本是打算做返回随机颜色
- /// </summary>
- /// <returns></returns>
- public static Scalar GetRandumScalar()
- {
- return new Scalar(0, 0, 255);
- }
- /// <summary>
- /// 深度copy
- /// </summary>
- /// <param name="src"></param>
- /// <returns></returns>
- public static List<OpenCvSharp.Point> CopyPoints(List<OpenCvSharp.Point> src)
- {
- List<OpenCvSharp.Point> dst = new List<OpenCvSharp.Point>();
- foreach (OpenCvSharp.Point point in src)
- {
- OpenCvSharp.Point p = new OpenCvSharp.Point();
- p.X = point.X;
- p.Y = point.Y;
- dst.Add(p);
- }
- return dst;
- }
- /// <summary>
- /// 获取周围的点的数量,并且判断结点
- /// </summary>
- /// <param name="points"></param>
- /// <param name="jiedian"></param>
- /// <param name="temp"></param>
- /// <returns></returns>
- public static int GetAroundNum(List<OpenCvSharp.Point> points, OpenCvSharp.Point jiedian, OpenCvSharp.Point temp)
- {
- if (points.IndexOf(temp) < 0)
- {
- return 2;
- }
- int i = 0;
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (points.IndexOf(zuo) >= 0)
- {
- if (zuo.X != jiedian.X || zuo.Y != jiedian.Y) i++;
- }
- if (points.IndexOf(zuo_shang) >= 0)
- {
- if (zuo_shang.X != jiedian.X || zuo_shang.Y != jiedian.Y) i++;
- }
- if (points.IndexOf(shang) >= 0)
- {
- if (shang.X != jiedian.X || shang.Y != jiedian.Y) i++;
- }
- if (points.IndexOf(you_shang) >= 0)
- {
- if (you_shang.X != jiedian.X || you_shang.Y != jiedian.Y) i++;
- }
- if (points.IndexOf(you) >= 0)
- {
- if (you.X != jiedian.X || you.Y != jiedian.Y) i++;
- }
- if (points.IndexOf(you_xia) >= 0)
- {
- if (you_xia.X != jiedian.X || you_xia.Y != jiedian.Y) i++;
- }
- if (points.IndexOf(xia) >= 0)
- {
- if (xia.X != jiedian.X || xia.Y != jiedian.Y) i++;
- }
- if (points.IndexOf(zuo_xia) >= 0)
- {
- if (zuo_xia.X != jiedian.X || zuo_xia.Y != jiedian.Y) i++;
- }
- return i;
- }
- /// <summary>
- /// 获取起点和终点的路径上的所有点
- /// </summary>
- /// <returns></returns>
- public static List<OpenCvSharp.Point> GetPassPoints(List<OpenCvSharp.Point> points,
- List<OpenCvSharp.Point> jiedians,
- OpenCvSharp.Point start,
- OpenCvSharp.Point end)
- {
- List<OpenCvSharp.Point> passPoints = new List<OpenCvSharp.Point>();
- List<OpenCvSharp.Point> copys = CopyPoints(points);
- OpenCvSharp.Point temp = start;
- bool loopFlag = true;
- do
- {
- int num = 0;
- copys.Remove(temp);
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (copys.IndexOf(zuo) >= 0)
- {
- temp = zuo;
- passPoints.Add(zuo);
- copys.Remove(zuo);
- num++;
- }
- if (copys.IndexOf(zuo_shang) >= 0)
- {
- temp = zuo_shang;
- passPoints.Add(zuo_shang);
- copys.Remove(zuo_shang);
- num++;
- }
- if (copys.IndexOf(shang) >= 0)
- {
- temp = shang;
- passPoints.Add(shang);
- copys.Remove(shang);
- num++;
- }
- if (copys.IndexOf(you_shang) >= 0)
- {
- temp = you_shang;
- passPoints.Add(you_shang);
- copys.Remove(you_shang);
- num++;
- }
- if (copys.IndexOf(you) >= 0)
- {
- temp = you;
- passPoints.Add(you);
- copys.Remove(you);
- num++;
- }
- if (copys.IndexOf(you_xia) >= 0)
- {
- temp = you_xia;
- passPoints.Add(you_xia);
- copys.Remove(you_xia);
- num++;
- }
- if (copys.IndexOf(xia) >= 0)
- {
- temp = xia;
- passPoints.Add(xia);
- copys.Remove(xia);
- num++;
- }
- if (copys.IndexOf(zuo_xia) >= 0)
- {
- temp = zuo_xia;
- passPoints.Add(zuo_xia);
- copys.Remove(zuo_xia);
- num++;
- }
- if (num > 1 || num == 0)
- loopFlag = false;
- }
- while (loopFlag);
- temp = end;
- loopFlag = true;
- do
- {
- int num = 0;
- copys.Remove(temp);
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (copys.IndexOf(zuo) >= 0)
- {
- temp = zuo;
- passPoints.Add(zuo);
- copys.Remove(zuo);
- num++;
- }
- if (copys.IndexOf(zuo_shang) >= 0)
- {
- temp = zuo_shang;
- passPoints.Add(zuo_shang);
- copys.Remove(zuo_shang);
- num++;
- }
- if (copys.IndexOf(shang) >= 0)
- {
- temp = shang;
- passPoints.Add(shang);
- copys.Remove(shang);
- num++;
- }
- if (copys.IndexOf(you_shang) >= 0)
- {
- temp = you_shang;
- passPoints.Add(you_shang);
- copys.Remove(you_shang);
- num++;
- }
- if (copys.IndexOf(you) >= 0)
- {
- temp = you;
- passPoints.Add(you);
- copys.Remove(you);
- num++;
- }
- if (copys.IndexOf(you_xia) >= 0)
- {
- temp = you_xia;
- passPoints.Add(you_xia);
- copys.Remove(you_xia);
- num++;
- }
- if (copys.IndexOf(xia) >= 0)
- {
- temp = xia;
- passPoints.Add(xia);
- copys.Remove(xia);
- num++;
- }
- if (copys.IndexOf(zuo_xia) >= 0)
- {
- temp = zuo_xia;
- passPoints.Add(zuo_xia);
- copys.Remove(zuo_xia);
- num++;
- }
- if (num > 1 || num == 0)
- loopFlag = false;
- }
- while (loopFlag);
- return passPoints;
- }
- /// <summary>
- /// 近似判断临近点是否再直线上
- /// </summary>
- /// <param name="points"></param>
- /// <param name="seed"></param>
- /// <returns></returns>
- public static bool IsNearPoint(List<OpenCvSharp.Point> points, OpenCvSharp.Point seed)
- {
- if (points.IndexOf(seed) >= 0)
- return true;
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(seed.X - 1, seed.Y);
- if (points.IndexOf(zuo) >= 0)
- return true;
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(seed.X - 1, seed.Y - 1);
- if (points.IndexOf(zuo_shang) >= 0)
- return true;
- OpenCvSharp.Point shang = new OpenCvSharp.Point(seed.X, seed.Y - 1);
- if (points.IndexOf(shang) >= 0)
- return true;
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(seed.X + 1, seed.Y - 1);
- if (points.IndexOf(you_shang) >= 0)
- return true;
- OpenCvSharp.Point you = new OpenCvSharp.Point(seed.X + 1, seed.Y);
- if (points.IndexOf(you) >= 0)
- return true;
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(seed.X + 1, seed.Y + 1);
- if (points.IndexOf(you_xia) >= 0)
- return true;
- OpenCvSharp.Point xia = new OpenCvSharp.Point(seed.X, seed.Y + 1);
- if (points.IndexOf(xia) >= 0)
- return true;
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(seed.X - 1, seed.Y + 1);
- if (points.IndexOf(zuo_xia) >= 0)
- return true;
- return false;
- }
- /// <summary>
- /// 检测两个点之间是否连通
- /// 程序不太对,还得在修改
- /// </summary>
- /// <param name="points"></param>
- /// <param name="pointa"></param>
- /// <param name="pointb"></param>
- /// <returns></returns>
- public static bool existLianTong(List<OpenCvSharp.Point> points, OpenCvSharp.Point pointa, OpenCvSharp.Point pointb)
- {
- List<OpenCvSharp.Point> copys = CopyPoints(points);
- bool lt = false;
- bool isis = true;
- OpenCvSharp.Point temp = pointa;
- do
- {
- bool inArr = false;
- copys.Remove(temp);
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (points.IndexOf(zuo) >= 0)
- {
- if (zuo.X == pointb.X && zuo.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = zuo;
- inArr = true;
- }
- if (points.IndexOf(zuo_shang) >= 0)
- {
- if (zuo_shang.X == pointb.X && zuo_shang.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = zuo_shang;
- inArr = true;
- }
- if (points.IndexOf(shang) >= 0)
- {
- if (shang.X == pointb.X && shang.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = shang;
- inArr = true;
- }
- if (points.IndexOf(you_shang) >= 0)
- {
- if (you_shang.X == pointb.X && you_shang.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = you_shang;
- inArr = true;
- }
- if (points.IndexOf(you) >= 0)
- {
- if (you.X == pointb.X && you.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = you;
- inArr = true;
- }
- if (points.IndexOf(you_xia) >= 0)
- {
- if (you_xia.X == pointb.X && you_xia.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = you_xia;
- inArr = true;
- }
- if (points.IndexOf(xia) >= 0)
- {
- if (xia.X == pointb.X && xia.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = xia;
- inArr = true;
- }
- if (points.IndexOf(zuo_xia) >= 0)
- {
- if (zuo_xia.X == pointb.X && zuo_xia.Y == pointb.Y)
- {
- lt = true;
- isis = false;
- }
- temp = zuo_xia;
- inArr = true;
- }
- if (!inArr) isis = false;
- } while (isis);
- return lt;
- }
- /// <summary>
- /// 判断删除当前点是否破坏连通性
- /// </summary>
- /// <returns></returns>
- public static bool panduanDestoryConn(List<OpenCvSharp.Point> points, OpenCvSharp.Point pointa)
- {
- List<OpenCvSharp.Point> copys = CopyPoints(points);
- OpenCvSharp.Point temp = pointa;
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- int a1 = Tools.GetAroundNum(points, temp, zuo);
- int a2 = Tools.GetAroundNum(points, temp, zuo_shang);
- int a3 = Tools.GetAroundNum(points, temp, shang);
- int a4 = Tools.GetAroundNum(points, temp, you_shang);
- int a5 = Tools.GetAroundNum(points, temp, you);
- int a6 = Tools.GetAroundNum(points, temp, you_xia);
- int a7 = Tools.GetAroundNum(points, temp, xia);
- int a8 = Tools.GetAroundNum(points, temp, zuo_xia);
- if (a1 >= 2 && a2 >= 2 && a3 >= 2 && a4 >= 2 && a5 >= 2 && a6 >= 2 && a7 >= 2 && a8 >= 2)
- {
- return false;
- }
- return true;
- }
- /// <summary>
- /// 寻找端点
- /// </summary>
- /// <param name="points"></param>
- /// <returns></returns>
- public static List<OpenCvSharp.Point> FindEndpoints(List<OpenCvSharp.Point> points)
- {
- List<OpenCvSharp.Point> endpoints = new List<OpenCvSharp.Point>();
- foreach (OpenCvSharp.Point point in points)
- {
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(point.X - 1, point.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(point.X - 1, point.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(point.X, point.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(point.X + 1, point.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(point.X + 1, point.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(point.X + 1, point.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(point.X, point.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(point.X - 1, point.Y + 1);
- int a = points.IndexOf(zuo) >= 0 ? 1 : 0;
- int b = points.IndexOf(zuo_shang) >= 0 ? 1 : 0;
- int c = points.IndexOf(shang) >= 0 ? 1 : 0;
- int d = points.IndexOf(you_shang) >= 0 ? 1 : 0;
- int e = points.IndexOf(you) >= 0 ? 1 : 0;
- int f = points.IndexOf(you_xia) >= 0 ? 1 : 0;
- int g = points.IndexOf(xia) >= 0 ? 1 : 0;
- int h = points.IndexOf(zuo_xia) >= 0 ? 1 : 0;
- int all = a + b + c + d + e + f + g + h;
- if (all == 1)
- {
- endpoints.Add(point);
- }
- else if (all == 2)
- {
- if (a == 1 && b == 1) endpoints.Add(point);
- if (b == 1 && c == 1) endpoints.Add(point);
- if (c == 1 && d == 1) endpoints.Add(point);
- if (d == 1 && e == 1) endpoints.Add(point);
- if (e == 1 && f == 1) endpoints.Add(point);
- if (f == 1 && g == 1) endpoints.Add(point);
- if (g == 1 && h == 1) endpoints.Add(point);
- if (h == 1 && a == 1) endpoints.Add(point);
- }
- }
- return endpoints;
- }
- /// <summary>
- /// 移除点
- /// </summary>
- /// <param name="points">连通域集合</param>
- /// <param name="pairs">已用的端点集合</param>
- public static List<OpenCvSharp.Point> RemoveSomePoint(List<OpenCvSharp.Point> points, List<OpenCvSharp.Point> pairs, List<OpenCvSharp.Point> jiedians)
- {
- List<OpenCvSharp.Point> copys = CopyPoints(points);
- foreach (OpenCvSharp.Point p1 in pairs)
- {
- bool nkkk = true;
- OpenCvSharp.Point temp = p1;
- do
- {
- bool isexit = false;
- copys.Remove(temp);
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (copys.IndexOf(zuo) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(zuo) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = zuo;
- copys.Remove(zuo);
- }
- }
- if (copys.IndexOf(zuo_shang) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(zuo_shang) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = zuo_shang;
- copys.Remove(zuo_shang);
- }
- }
- if (copys.IndexOf(shang) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(shang) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = shang;
- copys.Remove(shang);
- }
- }
- if (copys.IndexOf(you_shang) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(you_shang) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = you_shang;
- copys.Remove(you_shang);
- }
- }
- if (copys.IndexOf(you) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(you) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = you;
- copys.Remove(you);
- }
- }
- if (copys.IndexOf(you_xia) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(you_xia) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = you_xia;
- copys.Remove(you_xia);
- }
- }
- if (copys.IndexOf(xia) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(xia) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = xia;
- copys.Remove(xia);
- }
- }
- if (copys.IndexOf(zuo_xia) >= 0)
- {
- isexit = true;
- if (jiedians.IndexOf(zuo_xia) >= 0)
- {
- nkkk = false;
- }
- else
- {
- temp = zuo_xia;
- copys.Remove(zuo_xia);
- }
- }
- if (!isexit) nkkk = false;
- }
- while (nkkk);
- }
- return copys;
- }
- /// <summary>
- /// 寻找结点
- /// </summary>
- /// <param name="points"></param>
- /// <returns></returns>
- public static List<OpenCvSharp.Point> FindIntersectionPoint(List<OpenCvSharp.Point> points)
- {
- List<OpenCvSharp.Point> ps = new List<OpenCvSharp.Point>();
- //1左 2左上 3上 4右上 5右 6右下 7下 8左下
- for (int i = 0; i < points.Count - 1; i++)
- {
- OpenCvSharp.Point point = points[i];
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(point.X - 1, point.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(point.X - 1, point.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(point.X, point.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(point.X + 1, point.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(point.X + 1, point.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(point.X + 1, point.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(point.X, point.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(point.X - 1, point.Y + 1);
- int a = points.IndexOf(zuo) >= 0 ? 1 : 0;
- int b = points.IndexOf(zuo_shang) >= 0 ? 1 : 0;
- int c = points.IndexOf(shang) >= 0 ? 1 : 0;
- int d = points.IndexOf(you_shang) >= 0 ? 1 : 0;
- int e = points.IndexOf(you) >= 0 ? 1 : 0;
- int f = points.IndexOf(you_xia) >= 0 ? 1 : 0;
- int g = points.IndexOf(xia) >= 0 ? 1 : 0;
- int h = points.IndexOf(zuo_xia) >= 0 ? 1 : 0;
- int all = a + b + c + d + e + f + g + h;
- if (all > 2)
- {
- ps.Add(point);
- }
- }
- if (ps.Count > 1)
- {
- List<OpenCvSharp.Point> copys = CopyPoints(ps);
- for (int i = ps.Count - 1; i >= 0; i--)
- {
- OpenCvSharp.Point temp = ps[i];
- ps.Remove(temp);
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (ps.IndexOf(zuo) >= 0)
- {
- copys.Remove(zuo);
- }
- if (ps.IndexOf(zuo_shang) >= 0)
- {
- copys.Remove(zuo_shang);
- }
- if (ps.IndexOf(shang) >= 0)
- {
- copys.Remove(shang);
- }
- if (ps.IndexOf(you_shang) >= 0)
- {
- copys.Remove(you_shang);
- }
- if (ps.IndexOf(you) >= 0)
- {
- copys.Remove(you);
- }
- if (ps.IndexOf(you_xia) >= 0)
- {
- copys.Remove(you_xia);
- }
- if (ps.IndexOf(xia) >= 0)
- {
- copys.Remove(xia);
- }
- if (ps.IndexOf(zuo_xia) >= 0)
- {
- copys.Remove(zuo_xia);
- }
- }
- return copys;
- }
- return ps;
- }
- public static bool ExistInList(List<List<OpenCvSharp.Point>> lists, OpenCvSharp.Point point)
- {
- foreach (List<OpenCvSharp.Point> list in lists)
- {
- if (list.IndexOf(point) >= 0)
- {
- return true;
- }
- }
- return false;
- }
- /// <summary>
- /// 从一个端点出发,遇到结点,进行直线拟合
- /// </summary>
- /// <param name="copys"></param>
- /// <param name="point"></param>
- /// <returns></returns>
- public static bool FindLineFromOnePoint(List<OpenCvSharp.Point> copys, OpenCvSharp.Point point, out Line2D line)
- {
- //原集合的copy
- List<OpenCvSharp.Point> copys_1 = Tools.CopyPoints(copys);
- //用于存放起始点
- List<OpenCvSharp.Point> temps = new List<OpenCvSharp.Point>();
- int num = 0;
- OpenCvSharp.Point temp = point;
- copys_1.Remove(temp);
- do
- {
- num = 0;
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (copys_1.IndexOf(zuo) >= 0)
- {
- temp = zuo;
- copys_1.Remove(temp);
- temps.Add(zuo);
- num++;
- }
- if (copys_1.IndexOf(zuo_shang) >= 0)
- {
- temp = zuo_shang;
- copys_1.Remove(temp);
- temps.Add(zuo_shang);
- num++;
- }
- if (copys_1.IndexOf(shang) >= 0)
- {
- temp = shang;
- copys_1.Remove(temp);
- temps.Add(shang);
- num++;
- }
- if (copys_1.IndexOf(you_shang) >= 0)
- {
- temp = you_shang;
- copys_1.Remove(temp);
- temps.Add(you_shang);
- num++;
- }
- if (copys_1.IndexOf(you) >= 0)
- {
- temp = you;
- copys_1.Remove(temp);
- temps.Add(you);
- num++;
- }
- if (copys_1.IndexOf(you_xia) >= 0)
- {
- temp = you_xia;
- copys_1.Remove(temp);
- temps.Add(you_xia);
- num++;
- }
- if (copys_1.IndexOf(xia) >= 0)
- {
- temp = xia;
- copys_1.Remove(temp);
- temps.Add(xia);
- num++;
- }
- if (copys_1.IndexOf(zuo_xia) >= 0)
- {
- temp = zuo_xia;
- copys_1.Remove(temp);
- temps.Add(zuo_xia);
- num++;
- }
- }
- while (num == 1);
- if (temps.Count < 10)
- {
- temps.RemoveAt(temps.Count - 1);
- temps.RemoveAt(temps.Count - 1);
- }
- else
- {
- int delNum = temps.Count / 5;
- int min = temps.Count - delNum;
- for (int i = temps.Count - 1; i > min; i--)
- temps.Remove(temps[i]);
- }
- if (temps.Count >= 2)
- line = Cv2.FitLine(temps, DistanceTypes.Huber, 0, 0.01, 0.01);
- else
- line = new Line2D(0, 0, 0, 0);
- if (temps.Count < 4)
- {
- return false;
- }
- return true;
- /*if (line2D.Y1 > 0)
- {
- //这是获取直线上的点方程
- OpenCvSharp.Point a = new OpenCvSharp.Point((int)(line2D.X1 - 100 * line2D.Vx), (int)(line2D.Y1 - 100 * line2D.Vy));
- OpenCvSharp.Point b = new OpenCvSharp.Point((int)(line2D.X1 - 10 * line2D.Vx), (int)(line2D.Y1 - 10 * line2D.Vy));
- //Cv2.Line(origin, a, b, new Scalar(0, 0, 255), 2);
- //Cv2.ImWrite("C:\\Users\\zyh\\Desktop\\fuck.png", origin);
- }*/
- }
- /// <summary>
- /// 使用mul获取直线上的点
- /// </summary>
- /// <param name="line2D"></param>
- /// <param name="mul"></param>
- /// <returns></returns>
- public static OpenCvSharp.Point GetOnLineNextPoint(Line2D line2D, int mul)
- {
- //但是需要考虑直线垂直或平行x、y轴的时候
- return new OpenCvSharp.Point((int)(line2D.X1 - mul * line2D.Vx), (int)(line2D.Y1 - mul * line2D.Vy));
- }
- /// <summary>
- /// 使用直线方程获取直线上的点
- /// </summary>
- /// <param name="line2D"></param>
- /// <param name="point"></param>
- /// <returns></returns>
- public static int GetMulByPoint(Line2D line2D, OpenCvSharp.Point point)
- {
- if (line2D.Vy == 1)
- return (int)(line2D.Y1 - point.Y);
- if (line2D.Vx == 1)
- return (int)(line2D.X1 - point.X);
- if (line2D.Vx > 0.01)
- return (int)((line2D.X1 - point.X) / line2D.Vx);
- else
- return (int)((line2D.Y1 - point.Y) / line2D.Vy);
- }
- /// <summary>
- /// 获取相邻的点的数量
- /// </summary>
- /// <param name="points"></param>
- /// <param name="temp"></param>
- /// <returns></returns>
- public static int GetAroundNumWithNotJ(List<OpenCvSharp.Point> points, OpenCvSharp.Point temp)
- {
- int i = 0;
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- if (points.IndexOf(zuo) >= 0) i++;
- if (points.IndexOf(zuo_shang) >= 0) i++;
- if (points.IndexOf(shang) >= 0) i++;
- if (points.IndexOf(you_shang) >= 0) i++;
- if (points.IndexOf(you) >= 0) i++;
- if (points.IndexOf(you_xia) >= 0) i++;
- if (points.IndexOf(xia) >= 0) i++;
- if (points.IndexOf(zuo_xia) >= 0) i++;
- return i;
- }
- /// <summary>
- /// 判断点是否是端点
- /// </summary>
- /// <param name="points"></param>
- /// <param name="temp"></param>
- /// <returns></returns>
- public static bool FindEndpoints(List<OpenCvSharp.Point> points, OpenCvSharp.Point temp)
- {
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(temp.X - 1, temp.Y);
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(temp.X - 1, temp.Y - 1);
- OpenCvSharp.Point shang = new OpenCvSharp.Point(temp.X, temp.Y - 1);
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(temp.X + 1, temp.Y - 1);
- OpenCvSharp.Point you = new OpenCvSharp.Point(temp.X + 1, temp.Y);
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(temp.X + 1, temp.Y + 1);
- OpenCvSharp.Point xia = new OpenCvSharp.Point(temp.X, temp.Y + 1);
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(temp.X - 1, temp.Y + 1);
- int a = points.IndexOf(zuo) >= 0 ? 1 : 0;
- int b = points.IndexOf(zuo_shang) >= 0 ? 1 : 0;
- int c = points.IndexOf(shang) >= 0 ? 1 : 0;
- int d = points.IndexOf(you_shang) >= 0 ? 1 : 0;
- int e = points.IndexOf(you) >= 0 ? 1 : 0;
- int f = points.IndexOf(you_xia) >= 0 ? 1 : 0;
- int g = points.IndexOf(xia) >= 0 ? 1 : 0;
- int h = points.IndexOf(zuo_xia) >= 0 ? 1 : 0;
- int all = a + b + c + d + e + f + g + h;
- if (all == 1)
- {
- return true;
- }
- else if (all == 2)
- {
- if (a == 1 && b == 1) return true;
- if (b == 1 && c == 1) return true;
- if (c == 1 && d == 1) return true;
- if (d == 1 && e == 1) return true;
- if (e == 1 && f == 1) return true;
- if (f == 1 && g == 1) return true;
- if (g == 1 && h == 1) return true;
- if (h == 1 && a == 1) return true;
- }
- return false;
- }
- /// <summary>
- /// 移除临近点
- /// </summary>
- /// <param name="points"></param>
- /// <param name="endPoint"></param>
- public static void DeleteNearPoint(List<OpenCvSharp.Point> points, OpenCvSharp.Point startP)
- {
- points.Remove(startP);
- OpenCvSharp.Point seed = startP;
- int num;
- do
- {
- num = 0;
- int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0, h = 0;
- OpenCvSharp.Point a1 = new OpenCvSharp.Point(0, 0);
- OpenCvSharp.Point b1 = new OpenCvSharp.Point(0, 0);
- OpenCvSharp.Point c1 = new OpenCvSharp.Point(0, 0);
- OpenCvSharp.Point d1 = new OpenCvSharp.Point(0, 0);
- OpenCvSharp.Point e1 = new OpenCvSharp.Point(0, 0);
- OpenCvSharp.Point f1 = new OpenCvSharp.Point(0, 0);
- OpenCvSharp.Point g1 = new OpenCvSharp.Point(0, 0);
- OpenCvSharp.Point h1 = new OpenCvSharp.Point(0, 0);
- List<OpenCvSharp.Point> nears = new List<OpenCvSharp.Point>();
- OpenCvSharp.Point zuo = new OpenCvSharp.Point(seed.X - 1, seed.Y);
- if (points.IndexOf(zuo) >= 0)
- {
- a = 1;
- num++;
- a1 = zuo;
- nears.Add(zuo);
- }
- OpenCvSharp.Point zuo_shang = new OpenCvSharp.Point(seed.X - 1, seed.Y - 1);
- if (points.IndexOf(zuo_shang) >= 0)
- {
- b = 1;
- num++;
- b1 = zuo_shang;
- nears.Add(zuo_shang);
- }
- OpenCvSharp.Point shang = new OpenCvSharp.Point(seed.X, seed.Y - 1);
- if (points.IndexOf(shang) >= 0)
- {
- c = 1;
- num++;
- c1 = shang;
- nears.Add(shang);
- }
- OpenCvSharp.Point you_shang = new OpenCvSharp.Point(seed.X + 1, seed.Y - 1);
- if (points.IndexOf(you_shang) >= 0)
- {
- d = 1;
- num++;
- d1 = you_shang;
- nears.Add(you_shang);
- }
- OpenCvSharp.Point you = new OpenCvSharp.Point(seed.X + 1, seed.Y);
- if (points.IndexOf(you) >= 0)
- {
- e = 1;
- num++;
- e1 = you;
- nears.Add(you);
- }
- OpenCvSharp.Point you_xia = new OpenCvSharp.Point(seed.X + 1, seed.Y + 1);
- if (points.IndexOf(you_xia) >= 0)
- {
- f = 1;
- num++;
- f1 = you_xia;
- nears.Add(you_xia);
- }
- OpenCvSharp.Point xia = new OpenCvSharp.Point(seed.X, seed.Y + 1);
- if (points.IndexOf(xia) >= 0)
- {
- g = 1;
- num++;
- g1 = xia;
- nears.Add(xia);
- }
- OpenCvSharp.Point zuo_xia = new OpenCvSharp.Point(seed.X - 1, seed.Y + 1);
- if (points.IndexOf(zuo_xia) >= 0)
- {
- h = 1;
- num++;
- h1 = zuo_xia;
- nears.Add(zuo_xia);
- }
- if (num == 1)
- {
- if (a == 1) seed = a1;
- if (b == 1) seed = b1;
- if (c == 1) seed = c1;
- if (d == 1) seed = d1;
- if (e == 1) seed = e1;
- if (f == 1) seed = f1;
- if (g == 1) seed = g1;
- if (h == 1) seed = h1;
- points.Remove(nears[0]);
- }
- else if (num == 2)
- {
- if ((a == 1 && b == 1) || (b == 1 && c == 1) || (c == 1 && d == 1) ||
- (d == 1 && e == 1) || (e == 1 && f == 1) || (f == 1 && g == 1) ||
- (g == 1 && h == 1) || (h == 1 && a == 1))
- {
- if (a == 1 && b == 1)
- {
- if (!FindEndpoints(points, a1)) seed = a1;
- if (!FindEndpoints(points, b1)) seed = b1;
- }
- if (b == 1 && c == 1)
- {
- if (!FindEndpoints(points, c1)) seed = c1;
- if (!FindEndpoints(points, b1)) seed = b1;
- }
- if (c == 1 && d == 1)
- {
- if (!FindEndpoints(points, c1)) seed = c1;
- if (!FindEndpoints(points, d1)) seed = d1;
- }
- if (d == 1 && e == 1)
- {
- if (!FindEndpoints(points, e1)) seed = e1;
- if (!FindEndpoints(points, d1)) seed = d1;
- }
- if (e == 1 && f == 1)
- {
- if (!FindEndpoints(points, e1)) seed = e1;
- if (!FindEndpoints(points, f1)) seed = f1;
- }
- if (f == 1 && g == 1)
- {
- if (!FindEndpoints(points, g1)) seed = g1;
- if (!FindEndpoints(points, f1)) seed = f1;
- }
- if (g == 1 && h == 1)
- {
- if (!FindEndpoints(points, g1)) seed = g1;
- if (!FindEndpoints(points, h1)) seed = h1;
- }
- if (h == 1 && a == 1)
- {
- if (!FindEndpoints(points, a1)) seed = a1;
- if (!FindEndpoints(points, h1)) seed = h1;
- }
- points.Remove(nears[0]);
- points.Remove(nears[1]);
- num = 1;
- }
- }
- }
- while (num == 1);
- }
- public static Mat MergeMatFromMatArr(Mat[] arr)
- {
- Mat[] mats = new Mat[3];
- mats[0] = arr[0];
- mats[1] = arr[1];
- mats[2] = arr[2];
- Mat dst = new Mat();
- Cv2.Merge(mats, dst);
- return dst;
- }
- /// <summary>
- /// 形态学孔洞填充
- /// </summary>
- /// <param name="srcBw">二值图0/255</param>
- /// <returns></returns>
- public static Mat FillHole(Mat srcBw, Scalar scalar)
- {
- OpenCvSharp.Size m_Size = srcBw.Size();
- //创建扩展边界的图像
- Mat temp = Mat.Zeros(m_Size.Height + 2, m_Size.Width + 2, srcBw.Type());
- srcBw.CopyTo(new Mat(temp, new Range(1, m_Size.Height + 1), new Range(1, m_Size.Width + 1)));
- //new OpenCvSharp.Point(0, 0)
- Cv2.FloodFill(temp, new OpenCvSharp.Point(0, 0), scalar);
- //裁剪扩展边界的图像
- Mat cutImg = new Mat();
- new Mat(temp, new Range(1, m_Size.Height + 1), new Range(1, m_Size.Width + 1)).CopyTo(cutImg);
- return srcBw | (~cutImg);
- }
- public static int GetRandomNumber(int[] a)
- {
- Random rnd = new Random();
- int index = rnd.Next(a.Length);
- return a[index];
- }
- /// <summary>
- /// 寻找under cut
- /// </summary>
- /// <param name="temp"></param>
- /// <param name="mat"></param>
- /// <returns></returns>
- public static OpenCvSharp.Point GetLeftPoint(OpenCvSharp.Point temp, Mat mat)
- {
- Rect rect = new Rect();
- Mat mask = Mat.Zeros(mat.Rows + 2, mat.Cols + 2, MatType.CV_8UC1);
- Cv2.FloodFill(mat, mask, temp, new Scalar(255), out rect, null, null, FloodFillFlags.Link8);
- mask = mask * 255;
- List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();
- for (int h=1; h< mask.Height-1; h++)
- {
- for (int w = temp.X-150; w < temp.X; w++)
- {
- byte v = mask.At<byte>(h, w);
- if(v == 255)
- {
- //if(Cv2.FloodFill(mask, new OpenCvSharp.Point(w, h), new Scalar(255)) > 30)
- points.Add(new OpenCvSharp.Point(w, h));
- }
- }
- }
- List<OpenCvSharp.Point> points1 = points.FindAll(a => a.X < temp.X);
- if(points1.Count ==0)
- {
- return new OpenCvSharp.Point(0, 0);
- }
- int maxY = points1.Max(b => b.Y);
- List<OpenCvSharp.Point> points2 = points.FindAll(a => a.Y > maxY - 20);
- return points2.Find(a => a.X == points2.Min(b => b.X));
- //return points1.Find(a => a.Y == points1.Max(b => b.Y));
- }
- /// <summary>
- /// 找轮廓的最左、最右点
- /// </summary>
- /// <param name="temp"></param>
- /// <param name="mat"></param>
- /// <param name="type">1左 2右</param>
- /// <returns></returns>
- public static OpenCvSharp.Point GetLeftOrRightPoint(OpenCvSharp.Point temp, Mat mat, int type)
- {
- Rect rect = new Rect();
- Mat mask = Mat.Zeros(mat.Rows + 2, mat.Cols + 2, MatType.CV_8UC1);
- Cv2.FloodFill(mat, mask, temp, new Scalar(255), out rect, null, null, FloodFillFlags.Link8);
- mask = mask * 255;
- List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();
- if(type==2)
- {
- for (int h = 1; h < temp.Y-15/*mask.Height - 1*/; h++)
- {
- for (int w = temp.X; w < temp.X + 10/*0*/; w++)
- {
- byte v = mask.At<byte>(h, w);
- if (v == 255)
- {
- points.Add(new OpenCvSharp.Point(w, h));
- }
- }
- }
- }
- else
- {
- for (int h = temp.Y - 45; h < temp.Y-15/*mask.Height - 1*/; h++)
- {
- for (int w = temp.X - 200; w < temp.X + 200; w++)
- {
- byte v = mask.At<byte>(h, w);
- if (v == 255)
- {
- points.Add(new OpenCvSharp.Point(w, h));
- }
- }
- }
- }
- if (points.Count == 0) return temp;
- if (type == 1)
- {
- return points.Find(a => a.X == points.Min(b => b.X));
- }
- else
- {
- return points.Find(a => a.X == points.Max(b => b.X));
- }
- }
- public static int GetContoursHeight(OpenCvSharp.Point[] points, out OpenCvSharp.Point topPoint)
- {
- List<OpenCvSharp.Point> list = points.ToList();
- topPoint = list.Find(a => a.Y == list.Min(b => b.Y));
- OpenCvSharp.Point bottom = list.Find(a => a.Y == list.Max(b => b.Y));
- return bottom.Y - topPoint.Y;
- }
- static Mat calMats, phaseTempMin, phaseTempMax, phaseTemp1;
- static int dstChannel;
- static int dstWidth;
- static int localThreshold;
- /// <summary>
- /// 边缘增强
- /// </summary>
- /// <param name="mat"></param>
- /// <param name="kernel"></param>
- /// <param name="threshold"></param>
- /// <returns></returns>
- public unsafe static Mat adaptEdgeEnhancement(Mat mat, int kernel, int threshold)
- {
- Mat f = null;
- try
- {
- localThreshold = threshold;
- dstWidth = mat.Width;
- dstChannel = mat.Channels();
- phaseTemp1 = mat.Clone().CvtColor(ColorConversionCodes.GRAY2BGR);
- calMats = mat.Clone();
- //求最大值最小值
- Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(kernel, kernel));
- //腐蚀
- phaseTempMin = new Mat();
- Cv2.Erode(mat, phaseTempMin, element, null, 1, BorderTypes.Constant);
- //膨胀
- phaseTempMax = new Mat();
- Cv2.Dilate(mat, phaseTempMax, element, null, 1, BorderTypes.Constant);
- f = new Mat();
- Cv2.Subtract(phaseTempMax, phaseTempMin, f);
- f = f.CvtColor(ColorConversionCodes.GRAY2BGR);
- //实现边界增强
- f.ForEachAsVec3b(ForeachFunctionVeb3ForThreshold);
- }
- catch(Exception e)
- {
- }
- finally
- {
- if(calMats != null && !calMats.IsDisposed)
- {
- calMats.Dispose();
- calMats = null;
- }
- if (phaseTempMin != null && !phaseTempMin.IsDisposed)
- {
- phaseTempMin.Dispose();
- phaseTempMin = null;
- }
- if (phaseTempMax != null && !phaseTempMax.IsDisposed)
- {
- phaseTempMax.Dispose();
- phaseTempMax = null;
- }
- if (f != null && !f.IsDisposed)
- {
- f.Dispose();
- f = null;
- }
- }
- return phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY);
- }
- private unsafe static void ForeachFunctionVeb3ForThreshold(Vec3b* value, int* position)
- {
- ////对每个像素点的操作
- byte* pixels3 = (byte*)phaseTempMax.Data;
- byte* pixels4 = (byte*)phaseTempMin.Data;
- byte* pixels5 = (byte*)calMats.Data;
- int offset = (position[0] * dstWidth + position[1]) * dstChannel;
- Vec3b aa = new Vec3b(pixels5[offset], pixels5[offset + 1], pixels5[offset + 2]);
- bool toedit = false;
- if (value->Item0 > localThreshold)
- {
- toedit = true;
- byte ff = pixels3[offset];
- byte pp = pixels4[offset];
- if ((ff + pp) / 2 < aa.Item0)
- aa.Item0 = ff;
- else
- aa.Item0 = pp;
- }
- if (value->Item1 > localThreshold)
- {
- toedit = true;
- byte ff = pixels3[offset + 1];
- byte pp = pixels4[offset + 1];
- if ((ff + pp) / 2 < aa.Item1)
- aa.Item1 = ff;
- else
- aa.Item1 = pp;
- }
- if (value->Item2 > localThreshold)
- {
- toedit = true;
- byte ff = pixels3[offset + 2];
- byte pp = pixels4[offset + 2];
- if ((ff + pp) / 2 < aa.Item2)
- aa.Item2 = ff;
- else
- aa.Item2 = pp;
- }
- if (toedit)
- {
- phaseTemp1.Set(position[0], position[1], aa);
- }
- }
- public static List<int> CalcRepeatLines(List<int> line, Mat mat)
- {
- int value = 0;
- List<int> temp = new List<int>();
- //if (line.Count> 2 && mat.Row[line[line.Count - 1] + 9].CountNonZero() <= 300)
- // line.RemoveAt(line.Count - 1);
- for (int i=line.Count-1; i>=0; i--)
- {
- if(Math.Abs(line[i]-value)>=20)
- {
- value = line[i];
- temp.Add(line[i]);
- }
- }
- return temp;
- }
- public static Mat ImageSobel(Mat src)
- {
- Mat gray = null, xgrad = null, ygrad = null, output = null;
- try
- {
- //转为灰度
- gray = src.Clone();
- //Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
- MatType m = src.Type();
- //求 X 和 Y 方向的梯度 Sobel and scharr
- xgrad = new Mat();
- ygrad = new Mat();
- Cv2.Sobel(gray, xgrad, MatType.CV_16S, 1, 0, 3);
- Cv2.Sobel(gray, ygrad, MatType.CV_16S, 0, 1, 3);
- Cv2.ConvertScaleAbs(xgrad, xgrad);//缩放、计算绝对值并将结果转换为8位。不做转换的化显示不了,显示图相只能是8U类型
- Cv2.ConvertScaleAbs(ygrad, ygrad);
- //加强边缘检测
- //Cv2.Scharr(gray, xgrad, -1, 1, 0, 3);
- //Cv2.Scharr(gray, ygrad, -1, 0, 1, 3);
- output = new Mat(xgrad.Size(), xgrad.Type());
- //图像混合相加(基于权重 0.5)不精确
- //Cv2.AddWeighted(xgrad, 0.5, ygrad, 0.5, 0, output);
- //基于 算法 G=|Gx|+|Gy|
- int width = xgrad.Cols;
- int hight = xgrad.Rows;
- //基于 G= (Gx*Gx +Gy*Gy)的开方根
- for (int x = 0; x < hight; x++)
- {
- for (int y = 0; y < width; y++)
- {
- int xg = xgrad.At<byte>(x, y);
- int yg = ygrad.At<byte>(x, y);
- double v1 = Math.Pow(xg, 2);
- double v2 = Math.Pow(yg, 2);
- int val = (int)Math.Sqrt(v1 + v2);
- if (val > 255) //确保像素值在 0 -- 255 之间
- {
- val = 255;
- }
- if (val < 0)
- {
- val = 0;
- }
- byte xy = (byte)val;
- output.Set<byte>(x, y, xy);
- }
- }
- output.CopyTo(src);
- return src;
- }
- catch (Exception ex)
- {
- throw ex;
- }
- finally
- {
- if (gray != null) gray.Dispose();
- if (xgrad != null) gray.Dispose();
- if (ygrad != null) gray.Dispose();
- if (output != null) gray.Dispose();
- GC.Collect();
- }
- }
- }
- }
|