public unsafe int LabelIpp(IntPtr src, int bw, int bh, int stride, bool connectivity_4or8) { var matSrc = new Mat(bh, bw, MatType.CV_8UC1, src, stride); // label 버퍼 this.Labels = new Mat(bw, bw, MatType.CV_32SC1, Scalar.All(0)); int numLabels = 0; numLabels = IpDll.LabelMarker(src, (IntPtr)Labels.DataPointer, bw, bh, connectivity_4or8); // 4. 데이터 추출 var blobs = this.Blobs; blobs.Clear(); for (int i = 0; i < numLabels; i++) { int label = i + 1; blobs[label] = new MyBlob(label); } // labels 수정 for (int y = 0; y < bh; y++) { int *plabel = (int *)Labels.Ptr(y); for (int x = 0; x < bw; x++, plabel++) { var label = *plabel; if (label == 0) { continue; } var blob = blobs[label]; blob.area++; blob.centroidX += x; blob.centroidY += y; if (x < blob.MinX) { blob.MinX = x; } if (y < blob.MinY) { blob.MinY = y; } if (x > blob.MaxX) { blob.MaxX = x; } if (y > blob.MaxY) { blob.MaxY = y; } } } foreach (var blob in this.Blobs.Values) { blob.centroidX /= blob.area; blob.centroidY /= blob.area; } return(numLabels); }
public int LabelIpp(IntPtr src, int bw, int bh, int stride) { Glb.TimerStart(); // prepare byte *psrc = (byte *)src.ToPointer(); // label 버퍼 this.Labels = new int[bw * bh]; this.bw = bw; this.bh = bh; Console.WriteLine($"=> 1. Prepare buffer time: {Glb.TimerStop()}ms"); Glb.TimerStart(); int numLabels = 0; fixed(int *pLabels = Labels) { numLabels = IpDll.LabelMarker(src, (IntPtr)pLabels, bw, bh); } Console.WriteLine($"=> 2. IpDll.LabelMarker time: {Glb.TimerStop()}ms"); // 4. 데이터 추출 Glb.TimerStart(); var blobs = this.Blobs; blobs.Clear(); for (int i = 0; i < numLabels; i++) { int label = i + 1; blobs[label] = new MyBlob(label); } // labels 수정 for (int y = 0; y < bh; y++) { for (int x = 0; x < bw; x++) { var label = this.Labels[bw * y + x]; if (label == 0) { continue; } var blob = blobs[label]; blob.area++; blob.centroidX += x; blob.centroidY += y; if (x < blob.MinX) { blob.MinX = x; } if (y < blob.MinY) { blob.MinY = y; } if (x > blob.MaxX) { blob.MaxX = x; } if (y > blob.MaxY) { blob.MaxY = y; } } } foreach (var blob in this.Blobs.Values) { blob.centroidX /= blob.area; blob.centroidY /= blob.area; } Console.WriteLine($"=> 3. 데이터 추출 time: {Glb.TimerStop()}ms"); return(numLabels); }
public int Label(IntPtr src, int bw, int bh, int stride, bool connectivity_4or8) { var matSrc = new Mat(bh, bw, MatType.CV_8UC1, src, stride); // label 버퍼 this.Labels = new Mat(bw, bw, MatType.CV_32SC1, Scalar.All(0)); // link 테이블 int[] links = new int[bw * bh]; int linkCount = 1; // 1st stage // labeling with scan int[] nbrs = new int[4]; for (int y = 0; y < bh; y++) { byte *ps = (byte *)matSrc.Ptr(y); int * plabel = (int *)Labels.Ptr(y); for (int x = 0; x < bw; x++, ps++, plabel++) { // 배경이면 skip if (*ps == 0) { continue; } // 주변 4개의 label버퍼 조사 (l, tl, t, tr) int nbrCount = 0; int checkLabel; if (x != 0) { // check left checkLabel = plabel[-1]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } } if (y != 0) { // check top checkLabel = plabel[-bw]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } if (connectivity_4or8 == false) { if (x != 0) { // check lt checkLabel = plabel[-bw - 1]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } } if (x != bw - 1) { // check rt checkLabel = plabel[-bw + 1]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } } } } if (nbrCount == 0) { // 주변에 없다면 새번호 생성하고 라벨링 int newLabel = linkCount; * plabel = newLabel; // link 테이블에 새 루트 라벨 추가 links[linkCount] = 0; linkCount++; } else { // 주변에 있다면 주변 라벨들의 루트중 최소라벨 int minLabel = nbrs[0]; while (links[minLabel] != 0) { minLabel = links[minLabel]; } for (int i = 0; i < nbrCount; i++) { var label = nbrs[i]; while (links[label] != 0) { label = links[label]; } if (label < minLabel) { minLabel = label; } } *plabel = minLabel; // link 테이블에서 주변 라벨의 parent 수정 for (int i = 0; i < nbrCount; i++) { int label = nbrs[i]; // 라벨이 min라벨이 아니라면 라벨의 link를 minlabel로 바꿈 // 이전 link가 0이 아니라면 이전 link의 link도 minlabel로 바꿈 while (label != minLabel) { var oldLink = links[label]; links[label] = minLabel; if (oldLink == 0) { break; } label = oldLink; } } } } } // 2nd stage // links 수정 for (int i = 0; i < linkCount; i++) { if (links[i] == 0) { continue; } int label = links[i]; while (links[label] != 0) { label = links[label]; } links[i] = label; } // labels 수정 for (int y = 0; y < bh; y++) { int *plabel = (int *)Labels.Ptr(y); for (int x = 0; x < bw; x++, plabel++) { int label = *plabel; if (label == 0) { continue; } var link = links[label]; if (link == 0) { continue; } *plabel = link; } } // 3. 후처리 // link index 수정 Dictionary <int, int> relabelTable = new Dictionary <int, int>(); int newIndex = 1; for (int i = 1; i < linkCount; i++) { var link = links[i]; if (link == 0) { relabelTable.Add(i, newIndex++); } } // 4. 데이터 추출 var blobs = this.Blobs; blobs.Clear(); foreach (var newLable in relabelTable.Values) { blobs[newLable] = new MyBlob(newLable); } // labels 수정 for (int y = 0; y < bh; y++) { int *plabel = (int *)Labels.Ptr(y); for (int x = 0; x < bw; x++, plabel++) { var label = *plabel; if (label == 0) { continue; } int newLabel = relabelTable[label]; * plabel = newLabel; var blob = blobs[newLabel]; blob.area++; blob.centroidX += x; blob.centroidY += y; if (x < blob.MinX) { blob.MinX = x; } if (y < blob.MinY) { blob.MinY = y; } if (x > blob.MaxX) { blob.MaxX = x; } if (y > blob.MaxY) { blob.MaxY = y; } } } foreach (var blob in this.Blobs.Values) { blob.centroidX /= blob.area; blob.centroidY /= blob.area; } return(Blobs.Count); }
public int Label(IntPtr src, int bw, int bh, int stride) { Glb.TimerStart(); // prepare byte *psrc = (byte *)src.ToPointer(); // label 버퍼 this.Labels = new int[bw * bh]; this.bw = bw; this.bh = bh; // link 테이블 int[] links = new int[bw * bh]; int linkCount = 1; Console.WriteLine($"=> 1. Prepare buffer time: {Glb.TimerStop()}ms"); Glb.TimerStart(); // 1st stage // labeling with scan int[] nbrs = new int[4]; for (int y = 0; y < bh; y++) { for (int x = 0; x < bw; x++) { // 배경이면 skip if (psrc[stride * y + x] == 0) { continue; } // 주변 4개의 label버퍼 조사 (l, tl, t, tr) int nbrCount = 0; int checkLabel; if (x != 0) { // check left checkLabel = Labels[bw * y + x - 1]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } } if (y != 0) { // check top checkLabel = Labels[bw * (y - 1) + x]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } if (x != 0) { // check lt checkLabel = Labels[bw * (y - 1) + x - 1]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } } if (x != bw - 1) { // check rt checkLabel = Labels[bw * (y - 1) + x + 1]; if (checkLabel != 0) { nbrs[nbrCount++] = checkLabel; } } } if (nbrCount == 0) { // 주변에 없다면 새번호 생성하고 라벨링 int newLabel = linkCount; Labels[bw * y + x] = newLabel; // link 테이블에 새 루트 라벨 추가 links[linkCount] = 0; linkCount++; } else { // 주변에 있다면 주변 라벨들의 루트중 최소라벨 int minLabel = nbrs[0]; while (links[minLabel] != 0) { minLabel = links[minLabel]; } for (int i = 0; i < nbrCount; i++) { var label = nbrs[i]; while (links[label] != 0) { label = links[label]; } if (label < minLabel) { minLabel = label; } } Labels[bw * y + x] = minLabel; // link 테이블에서 주변 라벨의 parent 수정 for (int i = 0; i < nbrCount; i++) { int label = nbrs[i]; // 라벨이 min라벨이 아니라면 라벨의 link를 minlabel로 바꿈 // 이전 link가 0이 아니라면 이전 link의 link도 minlabel로 바꿈 while (label != minLabel) { var oldLink = links[label]; links[label] = minLabel; if (oldLink == 0) { break; } label = oldLink; } } } } } Console.WriteLine($"=> 2. 1st labelling time: {Glb.TimerStop()}ms"); // 2nd stage // links 수정 Glb.TimerStart(); for (int i = 0; i < linkCount; i++) { if (links[i] == 0) { continue; } int label = links[i]; while (links[label] != 0) { label = links[label]; } links[i] = label; } Console.WriteLine($"=> 3. link 수정 time: {Glb.TimerStop()}ms"); // labels 수정 Glb.TimerStart(); for (int y = 0; y < bh; y++) { for (int x = 0; x < bw; x++) { int label = Labels[bw * y + x]; if (label == 0) { continue; } var link = links[label]; if (link == 0) { continue; } Labels[bw * y + x] = link; } } Console.WriteLine($"=> 4. labels 수정 time: {Glb.TimerStop()}ms"); // 3. 후처리 // link index 수정 Glb.TimerStart(); Dictionary <int, int> relabelTable = new Dictionary <int, int>(); int newIndex = 1; for (int i = 1; i < linkCount; i++) { var link = links[i]; if (link == 0) { relabelTable.Add(i, newIndex++); } } Console.WriteLine($"=> 5. link index 수정 time: {Glb.TimerStop()}ms"); // 4. 데이터 추출 Glb.TimerStart(); var blobs = this.Blobs; blobs.Clear(); foreach (var newLable in relabelTable.Values) { blobs[newLable] = new MyBlob(newLable); } int labeledCount = 0; // labels 수정 for (int y = 0; y < bh; y++) { for (int x = 0; x < bw; x++) { var label = Labels[bw * y + x]; if (label == 0) { continue; } labeledCount++; int newLabel = relabelTable[label]; Labels[bw * y + x] = newLabel; var blob = blobs[newLabel]; blob.area++; blob.centroidX += x; blob.centroidY += y; if (x < blob.MinX) { blob.MinX = x; } if (y < blob.MinY) { blob.MinY = y; } if (x > blob.MaxX) { blob.MaxX = x; } if (y > blob.MaxY) { blob.MaxY = y; } } } foreach (var blob in this.Blobs.Values) { blob.centroidX /= blob.area; blob.centroidY /= blob.area; } Console.WriteLine($"=> 6. 데이터 추출 time: {Glb.TimerStop()}ms"); return(labeledCount); }