/// <summary> /// Using depth first search to find all non-white connected components. /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="visited"></param> /// <param name="ccResult"></param> public static void DFS(int width, int height, ref bool[,] visited, ConnectedComponent ccResult, Bitmap sourceImage) { int i = 0; int j = 0; try { for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { if (!(i == 0 && j == 0) && width + i >= 0 && width + i < sourceImage.Width && height + j >= 0 && height + j < sourceImage.Height && !visited[width + i, height + j] && calDiff(sourceImage.GetPixel(width, height), sourceImage.GetPixel(width + i, height + j)) <= ConfigParameters.DiffThreshold) { visited[width + i, height + j] = true; ccResult.PointSet.Add(new iPoint(width + i, height + j)); DFS(width + i, height + j, ref visited, ccResult, sourceImage); } } } } catch (Exception ecc) { throw new Exception(ecc.Message); } }
/// <summary> /// Find all connected-components in the image and return related information. /// </summary> /// <param name="sourceImage"></param> /// <returns></returns> public static List<ConnectedComponent> findAllConnectedComponents(Bitmap sourceImage) { int i = 0, j = 0; int width = sourceImage.Width; int height = sourceImage.Height; // The array which tells whether the point at position[i,j] has been visited. bool[,] visited = new bool[width, height]; List<ConnectedComponent> ccResult = new List<ConnectedComponent>(); try { for (i = 0; i < width; i++) { for (j = 0; j < height; j++) { if (!judgeWhitePoint(sourceImage.GetPixel(i, j)) && !visited[i, j]) { visited[i, j] = true; ConnectedComponent currentCC = new ConnectedComponent(); currentCC.PointSet.Add(new iPoint(i, j)); try { DFS(i, j, ref visited, currentCC, sourceImage); } catch (Exception ea) { throw new Exception(ea.Message); } FormatConnectedComponent(currentCC); ccResult.Add(currentCC); } } } } catch (Exception e) { throw new Exception(e.Message); } return ccResult; }
/// <summary> /// Merge different connected components into one. /// </summary> /// <param name="cc1"></param> /// <param name="cc2"></param> /// <returns></returns> public static ConnectedComponent mergeConnectedComponents(List<ConnectedComponent> cc) { // If there are only one element in the list, return the element directly. if (cc.Count == 1) { return cc[0]; } ConnectedComponent ccRet = new ConnectedComponent(); int minWidth = int.MaxValue, minHeight = int.MaxValue; int maxWidth = int.MinValue, maxHeight = int.MinValue; foreach (ConnectedComponent ccI in cc) { minWidth = ccI.Left_Top.Width_Position < minWidth ? ccI.Left_Top.Width_Position : minWidth; minHeight = ccI.Left_Top.Height_Position < minHeight ? ccI.Left_Top.Height_Position : minHeight; maxWidth = ccI.Right_Bottom.Width_Position > maxWidth ? ccI.Right_Bottom.Width_Position : maxWidth; maxHeight = ccI.Right_Bottom.Height_Position > maxHeight ? ccI.Right_Bottom.Height_Position : maxHeight; foreach (iPoint ponit in ccI.PointSet) { ccRet.PointSet.Add(ponit); } } ccRet.Left_Top = new iPoint(minWidth, minHeight); ccRet.Right_Bottom = new iPoint(maxWidth, maxHeight); return ccRet; }
/// <summary> /// Judge whether two connected components are similar in color. /// </summary> /// <param name="c1"></param> /// <param name="c2"></param> /// <returns></returns> private static bool judgeConnectedComponentsSimilar(ConnectedComponent c1, ConnectedComponent c2, Bitmap sourceImage) { bool flag = true; for (int i = 0; i < c1.PointSet.Count && flag; i++) { for (int j = 0; j < c2.PointSet.Count && flag; j++) { if (calDiff( sourceImage.GetPixel(c1.PointSet[i].Width_Position, c1.PointSet[i].Height_Position), sourceImage.GetPixel(c2.PointSet[j].Width_Position, c2.PointSet[j].Height_Position) ) > Config.ConfigParameters.DiffThreshold ) { flag = false; } } } return flag; }
/// <summary> /// Judge whether two connected components are near enough. /// </summary> /// <param name="c1"></param> /// <param name="c2"></param> /// <returns></returns> private static bool judgeConnectedComponentsNear(ConnectedComponent c1, ConnectedComponent c2) { double distance = calculateDistanceBetweenConnectedComponents(c1, c2); return distance - Config.ConfigParameters.DistanceThreshold < 0.00001 ? true : false; }
/// <summary> /// Calculate the size of certain connected component. /// </summary> /// <param name="cc"></param> /// <returns></returns> private static int calConnectedComponentsSize(ConnectedComponent cc) { int width = cc.Right_Bottom.Width_Position - cc.Left_Top.Width_Position; int height = cc.Right_Bottom.Height_Position - cc.Left_Top.Height_Position; return width * height; }
/// <summary> /// Calculate the distance of two connected components. /// </summary> /// <param name="c1"></param> /// <param name="c2"></param> /// <returns></returns> private static double calculateDistanceBetweenConnectedComponents(ConnectedComponent c1, ConnectedComponent c2) { double tmp = 0; double distance = double.MaxValue; foreach (iPoint point1 in c1.PointSet) { foreach (iPoint point2 in c2.PointSet) { tmp = calPointDistance(point1, point2); if (tmp < distance) { distance = tmp; } } } return distance; }
/// <summary> /// According to the point information to find the left-top and right-bottom point. /// </summary> /// <param name="currentCC"></param> private static void FormatConnectedComponent(ConnectedComponent currentCC) { int minWidth = int.MaxValue; int maxWidth = int.MinValue; int minHeight = int.MaxValue; int maxHeight = int.MinValue; foreach (iPoint point in currentCC.PointSet) { if (point.Width_Position < minWidth) { minWidth = point.Width_Position; } if (point.Width_Position > maxWidth) { maxWidth = point.Width_Position; } if (point.Height_Position < minHeight) { minHeight = point.Height_Position; } if (point.Height_Position > maxHeight) { maxHeight = point.Height_Position; } } currentCC.Left_Top = new iPoint(minWidth, minHeight); currentCC.Right_Bottom = new iPoint(maxWidth, maxHeight); }
/// <summary> /// Write one connected component to certain bmp image. /// </summary> /// <param name="ccImage"></param> /// <param name="sourceImage"></param> public static void write_Single_Connected_Component_To_Bmp(int tIndex, int index, ConnectedComponent ccImage, Bitmap sourceImage) { int width = ccImage.Right_Bottom.Width_Position - ccImage.Left_Top.Width_Position; int height = ccImage.Right_Bottom.Height_Position - ccImage.Left_Top.Height_Position; Bitmap ccBmp = new Bitmap(width + 1, height + 1, System.Drawing.Imaging.PixelFormat.Format24bppRgb); Graphics ccGraphics = Graphics.FromImage(ccBmp); // Set the background color as white. ccGraphics.Clear(Color.FromArgb(255, 255, 255)); ccGraphics.Dispose(); foreach (iPoint point in ccImage.PointSet) { ccBmp.SetPixel(point.Width_Position - ccImage.Left_Top.Width_Position, point.Height_Position - ccImage.Left_Top.Height_Position, sourceImage.GetPixel(point.Width_Position, point.Height_Position) ); } ccBmp.Save(ConfigParameters.CC_Image_Bmp_Path + tIndex.ToString() + "_" + index.ToString() + ".bmp"); }
public ConnectedComponent(ConnectedComponent _cc) { iniParameter(_cc.Left_Top, _cc.Right_Bottom, _cc.PointSet); }