/** * If the centre of a 3x3 is true then make the whole grid true * @param {BinaryImage} ref BinaryImage b [description] * @return {BinaryImage} The dilated image */ private BinaryImage dilation(BinaryImage b) { int[,] dirs = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } }; BinaryImage t = new BinaryImage(b.x, b.y); int w = b.x; // width int h = b.y; // height for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { if (b.Get(x + y * w)) { for (int z = 0; z < dirs.GetLength(0); z++) { int i = x + dirs[z, 0], j = y + dirs[z, 1]; if (i < w && i >= 0 && j < h && j >= 0) { t.Set(i + j * w, true); } } } } } return(t); }
internal static BinaryImage ToBinaryImage(this ImageSource image) { var bitmapImage = image as BitmapImage; var bmp = bitmapImage !.ToBitmap(); return(BinaryImage.FromImage(bmp)); }
// Get the adjancent point private bool nextPos(ref BinaryImage b, ref int pos, ref int currPos, ref int prevPos) { int w = b.x; if (currPos + w < b.Length && b.Get(currPos + w) && (currPos + w) != prevPos) { pos = currPos + w; // Top } else if ((currPos % w) + 1 < w && b.Get(currPos + 1) && (currPos + 1) != prevPos) { pos = currPos + 1; // Right } else if (currPos - w >= 0 && b.Get(currPos - w) && (currPos - w) != prevPos) { pos = currPos - w; // Bottom } else if ((currPos % w) - 1 >= 0 && b.Get(currPos - 1) && (currPos - 1) != prevPos) { pos = currPos - 1; // Left } else { return(false); // None } // Update values prevPos = currPos; currPos = pos; return(true); }
// Get the initial adjancent point private bool nextPos(ref BinaryImage b, ref int pos, int prevPos) { int w = b.x; if (prevPos + w < b.Length && b.Get(prevPos + w)) { pos = prevPos + w; // Top } else if ((prevPos % w) + 1 < w && b.Get(prevPos + 1)) { pos = prevPos + 1; // Right } else if (prevPos - w >= 0 && b.Get(prevPos - w)) { pos = prevPos - w; // Bottom } else if ((prevPos % w) - 1 >= 0 && b.Get(prevPos - 1)) { pos = prevPos - 1; // Left } else { return(false); // single pixel island } return(true); }
private Texture2D BinaryImage2TextureUsingPaths(BinaryImage b, List <List <Vector2> > paths) { List <Color> colorList = new List <Color>() { Color.red, Color.green, Color.blue, Color.magenta, Color.yellow }; Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; for (int i = 0; i < paths.Count && i < colorList.Count; i++) { for (int j = 0; j < paths[i].Count; j++) { t.SetPixel((int)paths[i][j].x, (int)paths[i][j].y, colorList[i]); } } t.Apply(); return(t); }
private int backTrack(ref BinaryImage b, ref List <Vector2> path, int start) { int w = b.x; if (start <= 1) { return(-1); } int currPos = (int)path[start].x + (int)path[start].y * w; int prevPos = (int)path[start - 1].x + (int)path[start - 1].y * w; if (currPos + w < b.Length && b.Get(currPos + w) && (currPos + w) != prevPos || // Top (currPos % w) + 1 < w && b.Get(currPos + 1) && (currPos + 1) != prevPos || // Right currPos - w >= 0 && b.Get(currPos - w) && (currPos - w) != prevPos || // Bottom (currPos % w) - 1 >= 0 && b.Get(currPos - 1) && (currPos - 1) != prevPos) { // Left return(start); } else { // if we cannot find any new points set back again. start = backTrack(ref b, ref path, start - 1); } return(start > 0 ? start : -1); }
void floodFill(ref BinaryImage b, ref List <int> i, int pos) { int w = b.x; if (b.Get(pos)) { i.Add(pos); b.Set(pos, false); } else { return; } if ((pos % w) + 1 < w) { floodFill(ref b, ref i, pos + 1); // Right } if ((pos % w) - 1 >= 0) { floodFill(ref b, ref i, pos - 1); // Left } if (pos + w < b.Length) { floodFill(ref b, ref i, pos + w); // Top } if (pos - w >= 0) { floodFill(ref b, ref i, pos - w); // Bottom } }
private void UpdateUI() { lvProcedures.Items.Clear(); if (document == null) { return; } BinaryImage image = document.Image; Dictionary <UInt16, int> segStat = new Dictionary <UInt16, int>(); foreach (Procedure proc in image.Procedures) { ListViewItem item = new ListViewItem(); item.Text = proc.EntryPoint.ToString(); //item.SubItems.Add(proc.ByteRange.Intervals.Count.ToString()); //item.SubItems.Add(proc.ByteRange.Length.ToString()); item.SubItems.Add("sub_" + proc.EntryPoint.LinearAddress.ToString()); item.SubItems.Add("?"); // proc.Bounds.Length.ToString()); item.Tag = proc; lvProcedures.Items.Add(item); segStat[proc.EntryPoint.Segment] = 1; } }
IEnumerator GenerateTerrain() { float t = Time.time; yield return(new WaitForEndOfFrame()); SimplexNoiseGenerator sng = new SimplexNoiseGenerator(seed); BinaryImage bi = new BinaryImage(tex.width, tex.height, false); for (int x = 0; x < tex.width; x++) { float height = sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 1, 200, 1.75f, 2f, 0.9f); height += sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 2, 25, 0.05f, 2f, 0.9f); height += sng.coherentNoise(x / terrainStretch + (transform.position.x * terrainStretch), 0, 0, 1, 25, 0.1f, 2f, 0.9f); for (int y = 0; y < tex.height; y++) { if (y < height * tex.height + 500) { bi.Set(x, y, true); } else { break; } } } binaryImage = bi; binaryImage = tidyBinaryImage(binaryImage); updateCollider(); Debug.Log((Time.time - t) * 1000f); }
public static void Recognize() { int n_images = Workspace.Images.Length; int i_image = n_images - 1; //i_image = 0; i_image = 2; string fileName = Workspace.Images[i_image]; string imageFile = Path.Combine(Workspace.InputFolder, fileName); string language = "eng"; int oem = (int)eOcrEngineMode.OEM_DEFAULT; string name = Path.GetFileNameWithoutExtension(imageFile); { using (Bitmap bmp = Bitmap.FromFile(imageFile) as Bitmap) { using (GreyImage greyImage = GreyImage.FromImage(bmp)) { ImageThresholder thresholder = new AdaptiveThresholder(); using (BinaryImage binImage = thresholder.Threshold(greyImage)) { DateTime started = DateTime.Now; DateTime ended = DateTime.Now; Rectangle[] rois = new Rectangle[] { Rectangle.FromLTRB(807, 43, 1351, 613), Rectangle.FromLTRB(4, 604, binImage.Width - 15, binImage.Height-35) }; int nROIs = rois.Length; string[] texts = new string[nROIs]; #if PARALLEL Parallel.For(0, nROIs, delegate(int iROI) #else using (TesseractProcessor processor = new TesseractProcessor()) for (int iROI = 0; iROI < nROIs; iROI++) #endif { #if PARALLEL using (TesseractProcessor processor = new TesseractProcessor()) #endif { Rectangle roi = rois[iROI]; { //oem = (int)eOcrEngineMode.OEM_TESSERACT_CUBE_COMBINED; processor.Init(Workspace.TessdataFolder, language, oem); processor.UseROI = true; processor.ROI = roi; unsafe { texts[iROI] = processor.RecognizeBinaryImage( binImage.BinaryData, binImage.Width, binImage.Height); } } } }
public void BinaryImage_Load_TrimsAllWhitespaces() { var binaryImageNode = new XElement(ElementNames.BinaryImage, "some text with spaces"); var binaryImage = new BinaryImage(); binaryImage.Load(binaryImageNode); binaryImage.Content.Should().Be("sometextwithspaces"); }
public void ReConstruct() { tex = oldtex; binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); updateCollider(); }
static oTesseractRequest __ocrExecute2(oTesseractRequest req, Bitmap bitmap) { using (TesseractProcessor processor = new TesseractProcessor()) { processor.InitForAnalysePage(); using (GreyImage greyImage = GreyImage.FromImage(bitmap)) { //greyImage.Save(ImageFormat.Bmp, outFile2); ImageThresholder thresholder = new AdaptiveThresholder(); using (BinaryImage binImage = thresholder.Threshold(greyImage)) { DocumentLayout doc = null; switch (req.command) { case TESSERACT_COMMAND.GET_TEXT: //string s = tes.GetText().Trim(); //req.output_text = s; //req.output_count = s.Length; req.ok = 1; break; default: unsafe { doc = processor.AnalyseLayoutBinaryImage( binImage.BinaryData, greyImage.Width, greyImage.Height); } if (doc != null) { var bs = new List <string>(); if (doc.Blocks.Count > 0) { for (int i = 0; i < doc.Blocks.Count; i++) { for (int j = 0; j < doc.Blocks[i].Paragraphs.Count; j++) { bs.AddRange(doc.Blocks[j].Paragraphs[j].Lines .Select(x => string.Format( "{0}_{1}_{2}_{3}", x.Left, x.Top, x.Right, x.Bottom))); } } } req.output_format = "left_top_right_bottom"; req.output_text = string.Join("|", bs.ToArray()); req.output_count = bs.Count; req.ok = 1; } break; } } } } return(req); }
// TODO: make into a coroutine?/separate thread private void updateCollider() { // binaryImage = tidyBinaryImage(binaryImage); BinaryImage binaryImageOutline = subtraction(binaryImage, erosion(binaryImage)); List <List <Vector2> > paths = getPaths(ref binaryImageOutline); gameObject.GetComponent <SpriteRenderer>().sprite = Sprite.Create(ApplyBinaryImage2Texture(ref tex, ref binaryImage), gameObject.GetComponent <SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); setCollider(ref paths); }
/** * Apply the edge detection algorithm to a BinaryImage. * Returns a copy of the image passed as parameter and does not modify the original **/ public static BinaryImage Apply(BinaryImage image) { BinaryImage mask = image.invert(); BinaryImage result; // initalise result to 0's bool[] bRes = new bool[image.Pixels.Length]; for (int i = 0; i < image.Pixels.Length; i++) { bRes[i] = false; } result = new BinaryImage(bRes, image.Width, image.Height); for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { bool res; if (y + 1 < image.Height) { // shift the image down, AND it with the mask res = mask.getPixel(x, y) && image.getPixel(x, y + 1); // OR this result with the result array result.setPixel(x, y, result.getPixel(x, y) || res); } if (y - 1 > 0) { // shift the image up, AND it with the mask res = mask.getPixel(x, y) && image.getPixel(x, y - 1); // OR this result with the result array result.setPixel(x, y, result.getPixel(x, y) || res); } if (x - 1 > 0) { // shift the image left, AND it with the mask res = mask.getPixel(x, y) && image.getPixel(x - 1, y); // OR this result with the result array result.setPixel(x, y, result.getPixel(x, y) || res); } if (x + 1 < image.Width) { // shift the image right, AND it with the mask res = mask.getPixel(x, y) && image.getPixel(x + 1, y); // OR this result with the result array result.setPixel(x, y, result.getPixel(x, y) || res); } } } return(result); }
static void Simple2_Recognize() { int n_images = Images.Length; int i_image = n_images - 1; //i_image = 0; string fileName = Images[i_image]; string imageFile = Path.Combine(InputFolder, fileName); string language = "eng"; int oem = (int)eOcrEngineMode.OEM_DEFAULT; using (TesseractProcessor processor = new TesseractProcessor()) { using (Bitmap bmp = Bitmap.FromFile(imageFile) as Bitmap) { using (GreyImage greyImage = GreyImage.FromImage(bmp)) { ImageThresholder thresholder = new AdaptiveThresholder(); using (BinaryImage binImage = thresholder.Threshold(greyImage)) { DateTime started = DateTime.Now; DateTime ended = DateTime.Now; int i = 3; //for (i = 0; i < 4; i++) //for (i = 3; i < 4; i++) { oem = i; processor.Init(TessdataFolder, language, oem); string text = ""; unsafe { started = DateTime.Now; text = processor.RecognizeBinaryImage( binImage.BinaryData, greyImage.Width, greyImage.Height); ended = DateTime.Now; Console.WriteLine("Duration recognition: {0} ms\n\n", (ended - started).TotalMilliseconds); } Console.WriteLine( string.Format("RecognizeMode: {1}\nRecognized Text:\n{0}\n++++++++++++++++++++++++++++++++\n", text, ((eOcrEngineMode)oem).ToString())); } } } } } }
private List <Vector2> getPath(ref BinaryImage b, int startPos) { List <Vector2> path = new List <Vector2>(); // Add start point to path path.Add(new Vector2(startPos % b.x, startPos / b.x)); int pos = 0, prevPos = startPos, currPos = startPos; bool open = true; if (!nextPos(ref b, ref pos, prevPos)) { // No other points found from the starting point means this is a single pixel island so we can remove it b.Set(currPos, false); return(null); } // While there is a next pos while (open) { if (nextPos(ref b, ref pos, ref currPos, ref prevPos)) { // b.Set(pos, false); if (currPos == startPos) { open = false; // We found a closed path } path.Add(new Vector2(currPos % b.x, currPos / b.x)); b.Set(currPos, false); } else { // If no next position, backtrack till we find a closed path var index = backTrack(ref b, ref path, path.Count - 1); if (index != -1) { // find next new point! path.RemoveRange(index + 1, path.Count - 1 - index); pos = (int)path[index].x + (int)path[index].y * b.x; prevPos = (int)path[index - 1].x + (int)path[index - 1].y * b.x; currPos = pos; } else { open = false; // If we cannot, close the path (this is the worst case and will give us a buggy collider) } } } return(path); }
/// <summary> /// Obtiene la informacion de una imagen en formato base64 /// </summary> /// <returns></returns> public string GetAsImage64() { String sdot = GetASDOT(); DOT dot = new DOT(); BinaryImage img = dot.ToPNG(sdot); img.Save(Path.Combine(folder, fname)); return(img.ToBase64String()); }
public static void Recognize() { int n_images = Workspace.Images.Length; int i_image = n_images - 1; i_image = 0; string fileName = Workspace.Images[i_image]; string imageFile = Path.Combine(Workspace.InputFolder, fileName); string language = "eng"; int oem = 3; TesseractProcessor processor = new TesseractProcessor(); using (Bitmap bmp = Bitmap.FromFile(imageFile) as Bitmap) { GreyImage greyImage = GreyImage.FromImage(bmp); DateTime started = DateTime.Now; AdaptiveThresholder thresholder = new AdaptiveThresholder(); BinaryImage binImage = thresholder.Threshold(greyImage); DateTime ended = DateTime.Now; Console.WriteLine("Duration thresholding: {0} ms", (ended - started).TotalMilliseconds); binImage.Invert(); //for (int i = 0; i < 4; i++) for (int i = 3; i < 4; i++) { oem = i; oem = (int)eOcrEngineMode.OEM_TESSERACT_CUBE_COMBINED; processor.Init(Workspace.TessdataFolder, language, oem); string text = ""; unsafe { started = DateTime.Now; //string text = processor.Recognize(bmp); text = processor.RecognizeBinaryImage( binImage.BinaryData, binImage.Width, binImage.Height); ended = DateTime.Now; Console.WriteLine("Duration recognition: {0} ms\n\n", (ended - started).TotalMilliseconds); } Console.WriteLine( string.Format("RecognizeMode: {1}\nText:\n{0}\n++++++++++++++++++++++++++++++++\n", text, ((eOcrEngineMode)oem).ToString())); } } }
/** * Generates a BitArray from a Texture2D * @param {Texture2D} t [] * @return {BitArray} [description] */ private BinaryImage BinaryImageFromTex(ref Texture2D t) { BinaryImage b = new BinaryImage(t.width, t.height); Color[] data = t.GetPixels(); for (int x = 0; x < b.Length; x++) { b.Set(x, data[x].a > 0); } return(b); }
private void GetBinaryImage() { if (DipLibImage is BinaryImage) { return; } if (!(DipLibImage is GrayscaleImage)) { GetGrayscaleImage(); } var grayscale = DipLibImage as GrayscaleImage; DipLibImage = new BinaryImage(grayscale.ToPixelsData(), grayscale.PixelWidth, grayscale.PixelHeight); }
// Use this for initialization void Start() { poly = gameObject.GetComponent <PolygonCollider2D>(); tex = Instantiate(gameObject.GetComponent <SpriteRenderer>().sprite.texture) as Texture2D; xBounds = gameObject.GetComponent <SpriteRenderer>().sprite.bounds.extents.x; yBounds = gameObject.GetComponent <SpriteRenderer>().sprite.bounds.extents.y; if (doInit) { binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); updateCollider(); } }
public static void generarOtraImagen(ParseTreeNode raiz) { try { String grafo_en_DOT = ControlDOT.ControlDOT.getDOT2(raiz); DOT dot = new DOT(); BinaryImage img = dot.ToPNG(grafo_en_DOT); img.Save("C:/Users/pablo/Desktop/Compi Junio/[Compi1]Practica1/[Compi1]Practica1/imagenes/ASA.png"); MessageBox.Show("Se creó el ASA."); } catch (Exception) { MessageBox.Show("No se creó el ASA."); } }
// TODO: make into a coroutine?/separate thread private void updateCollider() { tex = ApplyBinaryImage2Texture(ref tex, ref binaryImage); if (doSplit) { split(binaryImage); } // binaryImage = tidyBinaryImage(binaryImage); BinaryImage binaryImageOutline = subtraction(binaryImage, erosion(binaryImage)); List <List <Vector2> > paths = getPaths(ref binaryImageOutline); gameObject.GetComponent <SpriteRenderer>().sprite = Sprite.Create(tex, new Rect(0, 0, gameObject.GetComponent <SpriteRenderer>().sprite.rect.width, gameObject.GetComponent <SpriteRenderer>().sprite.rect.height), new Vector2(0.5f, 0.5f)); setCollider(ref paths); }
/** * Helper function to generate a Texture2D from a BinaryImage * @param {BinaryImage} b The BinaryImage to be converted to a Texture2D * @return {Texture2D} The generated Texture2D */ private Texture2D BinaryImage2Texture(BinaryImage b) { Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; for (int x = 0; x < t.width; x++) { for (int y = 0; y < t.height; y++) { t.SetPixel(x, y, b.Get(x + y * b.x) ? Color.white : Color.black); // if true then white else black } } t.Apply(); return(t); }
/** * Subtracts one binaryImage from another * @param {BinaryImage} b1 [description] * @param {BinaryImage} b2 [description] * @return {BinaryImage} [description] */ private BinaryImage subtraction(BinaryImage b1, BinaryImage b2) { BinaryImage t = new BinaryImage(b1.x, b1.y); int w = b1.x; // width int h = b1.y; // height for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { t.Set(x + y * w, (b1.Get(x + y * w) != b2.Get(x + y * w))); } } return(t); }
private Texture2D ApplyBinaryImage2Texture(ref Texture2D tex, ref BinaryImage b) { Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; Color[] data = tex.GetPixels(); for(int x=0; x<b.Length; x++){ if(!b.Get(x)) data[x].a = 0; } t.SetPixels(data); t.Apply(); return t; }
// Use this for initialization void Start() { poly = gameObject.GetComponent <PolygonCollider2D>(); tex = gameObject.GetComponent <SpriteRenderer>().sprite.texture; gameObject.GetComponent <SpriteRenderer>().sprite = Sprite.Create(tex, gameObject.GetComponent <SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); xBounds = gameObject.GetComponent <SpriteRenderer>().sprite.bounds.extents.x; yBounds = gameObject.GetComponent <SpriteRenderer>().sprite.bounds.extents.y; if (doInit) { binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); updateCollider(); } }
static void MainTest(string[] args) { { var disk = new Disk(); "Hello, World!".PackInto(disk.Words, 0); disk.WriteTo("hello.disk.txt"); disk.WriteTo("hello.disk.bin", raw: true); } int __break = 1; { var disk = new Disk("hello.disk.txt"); var msg = disk.Words.UnpackString(0); Console.WriteLine("Message: \"{0}\"", msg); } { var disk = new Disk(); disk.ReadFrom("hello.disk.bin", raw: true); var msg = disk.Words.UnpackString(0); Console.WriteLine("Message: \"{0}\"", msg); } { var fs = new Ssfs(); fs.Format(BinaryImage.ReadImage("boot/bootload.bin")); fs.AddFile("kernel.sys", BinaryImage.ReadImage("boot/kernel.sys")); fs.AddFile("hmd2043.drv", BinaryImage.ReadImage("boot/hmd2043.drv")); fs.AddFile("ssfs.drv", BinaryImage.ReadImage("boot/ssfs.drv")); fs.AddFile("shell.sys", BinaryImage.ReadImage("boot/shell.sys")); fs.AddFile("shell.ro", BinaryImage.ReadImage("boot/shell.ro")); fs.WriteTo("boot.disk.txt"); fs.WriteTo("boot.disk.bin", raw: true); } { var fs = new Ssfs("boot.disk.txt"); Console.WriteLine("List of files in boot.disk.txt:"); foreach (var file in fs.IterFiles()) { Console.WriteLine(" {0}", file.Path); } } }
// returns true if found a start point private bool findStartPos(ref BinaryImage b, ref int startPos) { int w = b.x, h = b.y; for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { if (b.Get(x + y * w)) { startPos = x + y * w; return(true); } } } return(false); // Cannot find any start points. }
// Use this for initialization void Start() { poly = gameObject.GetComponent <PolygonCollider2D>(); tex = Instantiate(gameObject.GetComponent <SpriteRenderer>().sprite.texture) as Texture2D; xBounds = gameObject.GetComponent <SpriteRenderer>().sprite.bounds.extents.x; yBounds = gameObject.GetComponent <SpriteRenderer>().sprite.bounds.extents.y; Sprite sprite = GetComponent <SpriteRenderer>().sprite; tex = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height); Color[] pixels; if (flip) { pixels = sprite.texture.GetPixels((int)sprite.textureRect.x, (int)sprite.textureRect.y, (int)sprite.textureRect.width, (int)sprite.textureRect.height); int xN = (int)sprite.textureRect.width; int yN = (int)sprite.textureRect.height; Color[] flipped = new Color[xN * yN]; for (int i = 0; i < xN; i++) { for (int j = 0; j < yN; j++) { flipped[(xN - i - 1) + j * xN] = pixels[i + j * xN]; } } pixels = flipped; } else { pixels = sprite.texture.GetPixels((int)sprite.textureRect.x, (int)sprite.textureRect.y, (int)sprite.textureRect.width, (int)sprite.textureRect.height); } tex.SetPixels(pixels); tex.Apply(); if (doInit) { binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); updateCollider(); } }
void Update() { if(doRefresh) { doRefresh = false; gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(tex, gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); } if(doBI) { doBI=false; binaryImage = BinaryImageFromTex(ref tex); gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(binaryImage), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); } if(doErosion) { doErosion=false; binaryImage = BinaryImageFromTex(ref tex); gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(erosion(binaryImage)), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); } if(doDilation) { doDilation=false; binaryImage = BinaryImageFromTex(ref tex); gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(dilation(binaryImage)), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); } if(doSub) { doSub=false; binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(subtraction(binaryImage, erosion(binaryImage))), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); } if(doSub2) { doSub2=false; binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(subtraction(binaryImage, erosion(binaryImage))), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); } if(doVert) { doVert=false; binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); BinaryImage binaryImageOutline = subtraction(binaryImage, erosion(binaryImage)); List<List<Vector2> > paths = getPaths(ref binaryImageOutline); gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create( BinaryImage2TextureUsingPaths(binaryImageOutline, paths), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); setCollider(ref paths); } if(doVertLong) { doVertLong=false; // TODO: simplify paths farther print("doVertLong has not been made yet :3"); gameObject.GetComponent<SpriteRenderer>().sprite = Sprite.Create(BinaryImage2Texture(binaryImage), gameObject.GetComponent<SpriteRenderer>().sprite.rect, new Vector2(0.5f, 0.5f)); } if(doComplete) { doComplete=false; binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); updateCollider(); } }
private BinaryImage tidyBinaryImage(BinaryImage b) { return dilation(erosion(b)); }
/** * Subtracts one binaryImage from another * @param {BinaryImage} b1 [description] * @param {BinaryImage} b2 [description] * @return {BinaryImage} [description] */ private BinaryImage subtraction(BinaryImage b1, BinaryImage b2) { BinaryImage t = new BinaryImage(b1.x, b1.y); int w = b1.x; // width int h = b1.y; // height for(int x=0; x<w; x++){ for(int y=0; y<h; y++){ t.Set(x+y*w, (b1.Get(x+y*w)!=b2.Get(x+y*w)) ); } } return t; }
// Use this for initialization void Start() { poly = gameObject.GetComponent<PolygonCollider2D>(); tex = Instantiate(gameObject.GetComponent<SpriteRenderer>().sprite.texture) as Texture2D; xBounds = gameObject.GetComponent<SpriteRenderer>().sprite.bounds.extents.x; yBounds = gameObject.GetComponent<SpriteRenderer>().sprite.bounds.extents.y; if(doInit) { binaryImage = BinaryImageFromTex(ref tex); binaryImage = tidyBinaryImage(binaryImage); updateCollider(); } }
void split(BinaryImage b) { int startPos; // TODO: copy the binaryImage instead of setting it BinaryImage t = new BinaryImage(b.x, b.y); for(int x=0; x<b.Length; x++) t.Set(x, b.Get(x)); List<List<int> > islands = new List<List<int> >(); // Find islands while(findStartPos(ref t, out startPos)) { List<int> island = new List<int>(); floodFill(ref t, ref island, startPos); islands.Add(island); } // If there is only 1 island we wont split anything if(islands.Count <= 1) return; // Get bounding boxes for each island for(int i=0; i<islands.Count; i++) { int x1, y1, x2, y2; x1 = x2 = islands[i][0]%b.x; y1 = y2 = Mathf.FloorToInt((float)islands[i][0]/b.x); // Find the smallest and biggest points for(int j=0; j<islands[i].Count; j++) { int x = islands[i][j]%b.x, y = Mathf.FloorToInt((float)islands[i][j]/b.x); if(x < x1) x1 = x; else if(x > x2) x2 = x; if(y < y1) y1 = y; else if(y > y2) y2 = y; } int w = x2-x1, h = y2-y1; // bounds int cx = (x2+x1)/2, cy = (y2+y1)/2; // new center for island // Create new gameobject GameObject go = new GameObject("DestructibleSpritePiece"); go.AddComponent<SpriteRenderer>(); go.AddComponent<Rigidbody2D>(); go.AddComponent<DestructibleSprite>(); go.GetComponent<DestructibleSprite>().doSplit = true; // Copy part of the original texture to our new texture Color32[] d = tex.GetPixels32(); Color32[] e = new Color32[w*h]; for(int x=0, y=0; x<d.Length; x++) { if(x%tex.width>=x1 && x%tex.width<x2 && Mathf.FloorToInt((float)x/tex.width)<y2 && Mathf.FloorToInt((float)x/tex.width)>=y1) { e[y] = d[x]; y++; } } // Apply to our new texture Texture2D texture = new Texture2D(w,h); texture.SetPixels32(e); texture.Apply(); // Add the spriteRenderer and apply the texture and inherit parent options SpriteRenderer s = go.GetComponent<SpriteRenderer>(); s.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); s.color = gameObject.GetComponent<SpriteRenderer>().color; s.sortingOrder = gameObject.GetComponent<SpriteRenderer>().sortingOrder; // Set the position to the new center go.transform.position = new Vector3(transform.position.x + (cx + pixelOffset)/pixelsToUnits - xBounds, transform.position.y + (cy + pixelOffset)/pixelsToUnits - yBounds, transform.position.z); // Put it in the same layer as the parent go.layer = gameObject.layer; } // We can destroy the orignal object Destroy(gameObject); }
/** * Generates a BitArray from a Texture2D * @param {Texture2D} t [] * @return {BitArray} [description] */ private BinaryImage BinaryImageFromTex(ref Texture2D t) { BinaryImage b = new BinaryImage(t.width, t.height); Color[] data = t.GetPixels(); for(int x=0; x<b.Length; x++) b.Set(x, data[x].a > 0 ); return b; }
// Get the initial adjancent point private bool nextPos(ref BinaryImage b, ref int pos, int prevPos) { int w = b.x; if( prevPos+w < b.Length && b.Get(prevPos+w)) pos = prevPos+w; // Top else if((prevPos%w)+1 < w && b.Get(prevPos+1)) pos = prevPos+1; // Right else if(prevPos-w >= 0 && b.Get(prevPos-w)) pos = prevPos-w; // Bottom else if((prevPos%w)-1 >= 0 && b.Get(prevPos-1)) pos = prevPos-1; // Left else return false; // single pixel island return true; }
private List<List<Vector2>> getPaths(ref BinaryImage b) { int startPos; List<List<Vector2> > paths = new List<List<Vector2> >(); while(findStartPos(ref b, out startPos)) { List<Vector2> path = new List<Vector2>(); // Find path path = getPath(ref b, startPos); if(path != null) paths.Add(path); } for(int i=0; i<paths.Count; i++) paths[i] = simplify(ref b, paths[i]); return paths; }
void floodFill(ref BinaryImage b, ref List<int> i, int pos) { int w = b.x; if(b.Get(pos)) { i.Add(pos); b.Set(pos, false); } else return; if((pos%w)+1 < w) floodFill(ref b, ref i, pos+1); // Right if((pos%w)-1 >= 0) floodFill(ref b, ref i, pos-1); // Left if(pos+w < b.Length) floodFill(ref b, ref i, pos+w); // Top if(pos-w >= 0) floodFill(ref b, ref i, pos-w); // Bottom }
// returns true if found a start point private bool findStartPos(ref BinaryImage b, out int startPos) { int w = b.x, h = b.y; for(int x= 0; x<w; x++){ for(int y= 0; y<h; y++){ if(b.Get(x + y*w)) { startPos = x + y*w; return true; } } } startPos = 0; return false; // Cannot find any start points. }
/** * If there is any true bits in a 3x3 grid make the centre bit false * @param {BinaryImage} ref BinaryImage b [description] * @return {BinaryImage} The erosion image */ private BinaryImage erosion(BinaryImage b) { int[,] dirs = {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}}; BinaryImage t = new BinaryImage(b.x, b.y, true); int w = b.x; // width int h = b.y; // height for(int x=0; x<w; x++) { for(int y=0; y<h; y++) { // t.Set(x + y*w, true); for(int z=0; z<dirs.GetLength(0); z++) { int i = x+dirs[z,0], j = y+dirs[z,1]; if(i<w && i>=0 && j<h && j>=0) { if(!b.Get(i + j*w)) t.Set(x + y*w, false); } else t.Set(x + y*w, false); } } } return t; }
/** * Helper function to generate a Texture2D from a BinaryImage * @param {BinaryImage} b The BinaryImage to be converted to a Texture2D * @return {Texture2D} The generated Texture2D */ private Texture2D BinaryImage2Texture(BinaryImage b) { Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; for(int x=0; x<t.width; x++) { for(int y=0; y<t.height; y++) { t.SetPixel(x, y, b.Get(x + y*b.x) ? Color.white : Color.black); // if true then white else black } } t.Apply(); return t; }
// Get the adjancent point private bool nextPos(ref BinaryImage b, ref int pos, ref int currPos, ref int prevPos) { int w = b.x; if( currPos+w < b.Length && b.Get(currPos+w) && (currPos+w)!=prevPos) pos = currPos+w; // Top else if((currPos%w)+1 < w && b.Get(currPos+1) && (currPos+1)!=prevPos) pos = currPos+1; // Right else if(currPos-w >= 0 && b.Get(currPos-w) && (currPos-w)!=prevPos) pos = currPos-w; // Bottom else if((currPos%w)-1 >= 0 && b.Get(currPos-1) && (currPos-1)!=prevPos) pos = currPos-1; // Left else return false; // None // Update values prevPos = currPos; currPos = pos; return true; }
private int backTrack(ref BinaryImage b, ref List<Vector2> path, int start) { int w = b.x; if(start <= 1) return -1; int currPos = (int)path[start].x + (int)path[start].y*w; int prevPos = (int)path[start-1].x + (int)path[start-1].y*w; if(currPos+w < b.Length && b.Get(currPos+w) && (currPos+w)!=prevPos || // Top (currPos%w)+1 < w && b.Get(currPos+1) && (currPos+1)!=prevPos || // Right currPos-w >= 0 && b.Get(currPos-w) && (currPos-w)!=prevPos || // Bottom (currPos%w)-1 >= 0 && b.Get(currPos-1) && (currPos-1)!=prevPos) { // Left return start; } else { // if we cannot find any new points set back again. start = backTrack(ref b, ref path, start-1); } return start>0?start:-1; }
// first stage of similification // Determine if we need to add this point(vertex) to the path private List<Vector2> simplify(ref BinaryImage b, List<Vector2> path) { List<Vector2> t = new List<Vector2>(); t.Add(path[0]); // remove straight line vertices for(int i=1; i<path.Count-1; i++) { if(path[i-1].x != path[i+1].x && path[i-1].y != path[i+1].y) { t.Add(path[i]); } } // TODO: clean this up // give the points a weight A(k)=ab/2, a = [k-1]-k, b = [k+1]-k float[] weight = new float[t.Count]; for(int k=1; k<t.Count-1; k++) { Vector2 i = t[k-1]-t[k], j = t[k+1]-t[k]; weight[k] = ( (Mathf.Sqrt(i.x*i.x+i.y*i.y))*(Mathf.Sqrt(j.x*j.x+j.y*j.y))/2 ); } List<Vector2> p = new List<Vector2>(); p.Add(t[0]); for(int i=1; i<t.Count-1; i++) { if( weight[i] > 1) p.Add(t[i]); // TODO: find better constant / average weight? W = (w0+..+wk) / k } p.Add(t[t.Count-1]); return p; }
private List<Vector2> getPath(ref BinaryImage b, int startPos) { List<Vector2> path = new List<Vector2>(); // Add start point to path path.Add(new Vector2(startPos%b.x, startPos/b.x)); int pos = 0, prevPos = startPos, currPos = startPos; bool open = true; if(!nextPos(ref b, ref pos, prevPos)) { // No other points found from the starting point means this is a single pixel island so we can remove it b.Set(currPos, false); return null; } // While there is a next pos while(open) { if(nextPos(ref b, ref pos, ref currPos, ref prevPos)) { // b.Set(pos, false); if(currPos == startPos) open = false; // We found a closed path path.Add(new Vector2(currPos%b.x, currPos/b.x)); b.Set(currPos, false); } else { // If no next position, backtrack till we find a closed path var index = backTrack(ref b, ref path, path.Count-1); if(index!=-1) { // find next new point! path.RemoveRange(index+1, path.Count-1-index); pos = (int)path[index].x + (int)path[index].y*b.x; prevPos = (int)path[index-1].x + (int)path[index-1].y*b.x; currPos = pos; } else open = false; // If we cannot, close the path (this is the worst case and will give us a buggy collider) } } return path; }
private Texture2D BinaryImage2TextureUsingPaths(BinaryImage b, List<List<Vector2> > paths) { List<Color> colorList = new List<Color>() { Color.red, Color.green, Color.blue, Color.magenta, Color.yellow }; Texture2D t = new Texture2D(b.x, b.y); t.wrapMode = TextureWrapMode.Clamp; for(int i=0; i<paths.Count && i<colorList.Count; i++) { for(int j=0; j<paths[i].Count; j++) { t.SetPixel((int)paths[i][j].x, (int)paths[i][j].y, colorList[i]); } } t.Apply(); return t; }