using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using UTIL; namespace Test_img { public partial class Form1 : Form { public struct FIFO_ITEM { public UInt16 x; public UInt16 y; } unsafe public struct THE_POINT { public FIFO_ITEM* pi; public Byte* pm; } public struct CLUSTER_COORD { public UInt16 count; // number of points (pixels) in cluster public Byte excluded; // flag, cluster should be ignored if TRUE public Byte marker; // cluster identicator public ARM_RECT rect; // rectangular area of cluster (in pixels) } public struct ARM_RECT { public UInt16 left; public UInt16 top; public UInt16 right; public UInt16 bottom; } const UInt16 CELL_SIZE = 8; // cluster cell size, in pix const Byte __FALSE = 0; const Byte __TRUE = 1; const Byte NO_MARKER = 0; // 'no marker' cluster identifier //static UInt16 IMAGE_CELL_CX = (UInt16)((IMAGE_CX + CELL_SIZE - 1) / CELL_SIZE); //static UInt16 IMAGE_CELL_CY = (UInt16)((IMAGE_CY + CELL_SIZE - 1) / CELL_SIZE); static UInt16 IMAGE_CELL_CX = 0; // (UInt16)((IMAGE_CX + CELL_SIZE - 1) / CELL_SIZE); static UInt16 IMAGE_CELL_CY = 0; // (UInt16)((IMAGE_CY + CELL_SIZE - 1) / CELL_SIZE); List v = new List(); List FIFO_ITEM_f = new List(); static UInt16 IMAGE_CX = 0; static UInt16 IMAGE_CY = 0; static FIFO_ITEM[] g_shot_array = new FIFO_ITEM[4096]; // shot XY-coordinates from FIFO1 static UInt16 g_shot_count; // number of shot XY-coordinate pairs in FIFO1 static UInt16 g_cluster_count; // number of clusters (8x8) in FIFO1 static UInt16 g_super_cluster_count; // number of super clusters in FIFO1 static CLUSTER_COORD[] g_cluster_coords = null; // new CLUSTER_COORD[IMAGE_CELL_CX * IMAGE_CELL_CY]; // clusters mass centre & coordinates in FIFO1 static CLUSTER_COORD[] g_cluster_ptrs = null; // new CLUSTER_COORD[IMAGE_CELL_CX * IMAGE_CELL_CY]; // static CLUSTER_COORD[] g_super_cluster_coords = null; // new CLUSTER_COORD[IMAGE_CELL_CX * IMAGE_CELL_CY]; StreamWriter logsw = null; private void SearchClusters(UInt16 porog) { InitClusters(); GetPix(porog); BuildClustersArray(); EnlargeClustersInArray(); } private void InitClusters() { IMAGE_CX = (UInt16)(bm.Width - 1); IMAGE_CY = (UInt16)(bm.Height - 1); IMAGE_CELL_CX = (UInt16)((IMAGE_CX + CELL_SIZE - 1) / CELL_SIZE); IMAGE_CELL_CY = (UInt16)((IMAGE_CY + CELL_SIZE - 1) / CELL_SIZE); g_cluster_coords = new CLUSTER_COORD[IMAGE_CELL_CX * IMAGE_CELL_CY]; // clusters mass centre & coordinates in FIFO1 g_cluster_ptrs = new CLUSTER_COORD[IMAGE_CELL_CX * IMAGE_CELL_CY]; // g_super_cluster_coords = new CLUSTER_COORD[IMAGE_CELL_CX * IMAGE_CELL_CY]; String logfilename = "log_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".log"; //logsw = new StreamWriter(logfilename, false); //logsw.WriteLine($"IMAGE_CX {IMAGE_CX}"); //logsw.WriteLine($"IMAGE_CY {IMAGE_CY}"); //logsw.WriteLine($"IMAGE_CELL_CX {IMAGE_CELL_CX}"); //logsw.WriteLine($"IMAGE_CELL_CY {IMAGE_CELL_CY}"); //logsw.WriteLine($"g_cluster_coords {IMAGE_CELL_CX * IMAGE_CELL_CY}"); //logsw.WriteLine($"g_cluster_ptrs {IMAGE_CELL_CX * IMAGE_CELL_CY}"); //logsw.WriteLine($"g_super_cluster_coords {IMAGE_CELL_CX * IMAGE_CELL_CY}"); //logsw.WriteLine(); } private void GetPix(UInt16 porog) { UnsafeBitmap btm = new UnsafeBitmap(bm); btm.LockBitmap(); g_shot_count = 0; for (int y = 0; y < bm.Height; y++) { for (int x = 0; x < bm.Width; x++) { PixelData c = btm.GetPixel(x, y); if (c.blue >= porog) { FIFO_ITEM t = new FIFO_ITEM(); t.x = (UInt16)x; t.y = (UInt16)y; //logsw.WriteLine($"Shoot n={g_shot_count} x={x} y={y}"); g_shot_array[g_shot_count++] = t; v.Add(t); } } } btm.UnlockBitmap(); btm.Dispose(); //logsw.WriteLine(); } private void BuildClustersArray() { Byte marker; UInt16 i, j, k, count; UInt16 l, t, r, b; for (i = 0; i < g_shot_count; i++) { FIFO_ITEM fi = g_shot_array[i]; UInt16 x = (UInt16)(fi.x / CELL_SIZE); UInt16 y = (UInt16)(fi.y / CELL_SIZE); g_cluster_coords[y * IMAGE_CELL_CX + x].count++; g_cluster_coords[y * IMAGE_CELL_CX + x].excluded = __FALSE; g_cluster_coords[y * IMAGE_CELL_CX + x].marker = NO_MARKER; g_cluster_coords[y * IMAGE_CELL_CX + x].rect.left = (UInt16)(x * CELL_SIZE); g_cluster_coords[y * IMAGE_CELL_CX + x].rect.top = (UInt16)(y * CELL_SIZE); g_cluster_coords[y * IMAGE_CELL_CX + x].rect.right = (UInt16)((x + 1) * CELL_SIZE); g_cluster_coords[y * IMAGE_CELL_CX + x].rect.bottom = (UInt16)((y + 1) * CELL_SIZE); //logsw.WriteLine($"Cl_1 i={i} n={y * IMAGE_CELL_CX + x} " + // $"count={g_cluster_coords[y * IMAGE_CELL_CX + x].count - 1} " + // $"excluded={g_cluster_coords[y * IMAGE_CELL_CX + x].excluded} " + // $"marker={g_cluster_coords[y * IMAGE_CELL_CX + x].marker} " + // $"left={(UInt16)(x * CELL_SIZE)} " + // $"top={(UInt16)(y * CELL_SIZE)} " + // $"right={(UInt16)((x + 1) * CELL_SIZE)} " + // $"bottom={(UInt16)((y + 1) * CELL_SIZE)}"); } //logsw.WriteLine(); g_cluster_count = 0; for (i = 0; i < IMAGE_CELL_CX * IMAGE_CELL_CY; i++) { if (g_cluster_coords[i].count > 0) { //logsw.WriteLine($"Cl_2 i={i} g_cluster_count{g_cluster_count} x={g_cluster_coords[i].rect.left} y={g_cluster_coords[i].rect.top}"); g_cluster_ptrs[g_cluster_count++] = g_cluster_coords[i]; } } //logsw.WriteLine(); marker = NO_MARKER; for (i = 0; i < g_cluster_count; i++) { Int16 x1 = (Int16)((g_cluster_ptrs[i].rect.left + g_cluster_ptrs[i].rect.right) / 2); Int16 y1 = (Int16)((g_cluster_ptrs[i].rect.top + g_cluster_ptrs[i].rect.bottom) / 2); if (g_cluster_ptrs[i].marker == NO_MARKER) g_cluster_ptrs[i].marker = (++marker); for (j = (UInt16)(i + 1); j < g_cluster_count; j++) { Int16 x2 = (Int16)((g_cluster_ptrs[j].rect.left + g_cluster_ptrs[j].rect.right) / 2); Int16 y2 = (Int16)((g_cluster_ptrs[j].rect.top + g_cluster_ptrs[j].rect.bottom) / 2); if (Math.Abs(x1 - x2) <= CELL_SIZE && Math.Abs(y1 - y2) <= CELL_SIZE) { if (g_cluster_ptrs[j].marker == NO_MARKER) { g_cluster_ptrs[j].marker = g_cluster_ptrs[i].marker; } else { for (k = 0; k < g_cluster_count; k++) { if (g_cluster_ptrs[k].marker == g_cluster_ptrs[j].marker) { g_cluster_ptrs[k].marker = g_cluster_ptrs[i].marker; //logsw.WriteLine($"Cl_3 i={i} j={j} k={k} x={g_cluster_ptrs[k].rect.left} y={g_cluster_ptrs[k].rect.top} m={g_cluster_ptrs[k].marker}"); } } } } } } //logsw.WriteLine(); g_super_cluster_count = 0; for (i = 1; i <= marker; i++) { count = 0; l = 0x7fff; t = 0x7fff; r = 0; b = 0; for (j = 0; j < g_cluster_count; j++) { if (g_cluster_ptrs[j].marker == i) { if (g_cluster_ptrs[j].rect.left < l) l = g_cluster_ptrs[j].rect.left; if (g_cluster_ptrs[j].rect.top < t) t = g_cluster_ptrs[j].rect.top; if (g_cluster_ptrs[j].rect.right > r) r = g_cluster_ptrs[j].rect.right; if (g_cluster_ptrs[j].rect.bottom > b) b = g_cluster_ptrs[j].rect.bottom; count += g_cluster_ptrs[j].count; } } if (count > 0) { g_super_cluster_coords[g_super_cluster_count].count = count; g_super_cluster_coords[g_super_cluster_count].excluded = __FALSE; g_super_cluster_coords[g_super_cluster_count].marker = NO_MARKER; g_super_cluster_coords[g_super_cluster_count].rect.left = l; g_super_cluster_coords[g_super_cluster_count].rect.top = t; g_super_cluster_coords[g_super_cluster_count].rect.right = r; g_super_cluster_coords[g_super_cluster_count].rect.bottom = b; g_super_cluster_count++; } } //for (int m = 0; m < g_super_cluster_count; m++) //{ // logsw.WriteLine($"Cl_5 m={m} " + // $"count={g_super_cluster_coords[m].count} " + // $"excluded={g_super_cluster_coords[m].excluded} " + // $"marker={g_super_cluster_coords[m].marker} " + // $"left={g_super_cluster_coords[m].rect.left} " + // $"top={g_super_cluster_coords[m].rect.top} " + // $"right={g_super_cluster_coords[m].rect.right} " + // $"bottom={g_super_cluster_coords[m].rect.bottom}"); //} //logsw.Close(); } private void EnlargeClustersInArray() { UInt16 i; for (i = 0; i < g_super_cluster_count; i++) { if (g_super_cluster_coords[i].rect.left >= CELL_SIZE) g_super_cluster_coords[i].rect.left -= CELL_SIZE; if (g_super_cluster_coords[i].rect.top >= CELL_SIZE) g_super_cluster_coords[i].rect.top -= CELL_SIZE; if (g_super_cluster_coords[i].rect.right <= IMAGE_CX - CELL_SIZE) g_super_cluster_coords[i].rect.right += CELL_SIZE; if (g_super_cluster_coords[i].rect.bottom <= IMAGE_CY - CELL_SIZE) g_super_cluster_coords[i].rect.bottom += CELL_SIZE; } } private Rectangle CLUSTER_COORD2Rect(CLUSTER_COORD c) { return new Rectangle(c.rect.left, c.rect.top, c.rect.right - c.rect.left, c.rect.bottom - c.rect.top); } } }