Skip to content

Instantly share code, notes, and snippets.

@leestuartx
Created April 2, 2015 20:47
Show Gist options
  • Save leestuartx/b808fd855bdea8f09d9c to your computer and use it in GitHub Desktop.
Save leestuartx/b808fd855bdea8f09d9c to your computer and use it in GitHub Desktop.
Image Tracking in Unity
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public enum ImageDetectAlgorithm
{
corner,
fill,
blobs, //corner detect, edge detect and Fill
}
public class BlobData
{
public string name = "new object";
public List<Vector2> edgesFound; //List of all the edges for the current tracked building
public List<Vector2> cornersFound;
}
public class PixelRecognition : MonoBehaviour
{
public GUITexture videoFootage; //Main texture for tracking
public GameObject ScannedImageObject;
Color32[] imageColors; //Local copy of texture's pixel values
public ImageDetectAlgorithm curDetectionScheme = ImageDetectAlgorithm.fill;
//-------------------------------------------------
//Details about each tracked object
//-------------------------------------------------
List<BlobData> blobData = new List<BlobData>();
private bool hasFoundNewObject; // Used to advance the program to check for an object's edges
private List<Vector2> edgesFound = new List<Vector2>(); //List of all the edges for the current tracked building
private List<Vector2> cornersFound = new List<Vector2>();
//---------------------------------
// DEBUG GUI
//---------------------------------
public Text statusLabel; //Displays progress messages for the tracking procedure
public Text blobDetailLabel; //Displays the stats of each detected object on screen
private string accumStatus = "Status: ";
private int charCount = 0;
private float searchDistance = 3f; //Pixel Polygon detection distance (3 seems to be the best setting)
private float cornerMinRadius = 0.54f; //Used to determine min angle allowed for a corner to be detected
//Steps required to track an object
private bool step1 = true;
private bool step2 = false;
private bool step3 = false;
private bool step4 = false;
//The current surrounding pixel to be tracked
SearchDirection curDirection = SearchDirection.right;
SearchDirection lastDirection = SearchDirection.right;
//Vars used for keeping track of surrounding pixels
private bool mark1;
private bool mark2;
private bool mark3;
private bool mark4;
private bool mark5;
private bool mark6;
private bool mark7;
private bool mark8;
private bool mark9;
int lastSelectedPos = 3; //The pixel position on a grid of 9 pixels, which is the current pixel and the surrounding 8 pixels
//If there are more identical colors on the top then we will start detecting direction from the bottom, otherwise we will start detecting from the top
int upperHalfCount = 0;
int lowerHalfCount = 0;
//-------------------------------------------------
//Colors used for searching for pixels
//-------------------------------------------------
public int errorCorrect = 20;
public int matchingColorErrorCorrect = 2;
public Color32 buildingColor = new Color32(244, 243, 236, 1);
Color32 EdgeColor = new Color32(0, 0, 255, 1);
Color Black = new Color(0f, 0f, 0f, 1.0f);
Color Green = new Color(0f, 1f, 0f, 1.0f);
Color Red = new Color(1f, 0f, 0f, 1.0f);
public bool debugDrawProgress = true;
public int pixelCancelationValue = 4; //The difference between pixels colors to not count as the same building
int totalErrors = 0;
int matchingColorCount = 0;
private bool hasStartedEdgeDetect;
private bool hasSetNextDirection;
private bool hasFinishedCheckingDirection;
private bool doCornerCheckRoutine = true;
private bool hasStartedProcess = false;
//--------------------------------
// GOOGLE MAPS VARS
//--------------------------------
//Used for keeping accurate latitude and longitude from tracking a google map
private int zoomLevel;
public int mapSize;
void Start()
{
// DoRecognition();
}
int CoordToPixelArray(Vector2 coords)
{
//SetStatus("coordX:" + coords.x + " coordY:" + coords.y + " texWidth:" + videoFootage.texture.width);
int index = (int)(coords.x + coords.y * videoFootage.texture.width);
return index;
}
Vector2 arrayToXYCoord(int curIndex)
{
int width = (int)videoFootage.texture.width;
int curY = curIndex / width;
int curX = curIndex % width;
return new Vector2(curX, curY);
}
public bool HasStartedTracking()
{
return hasStartedProcess;
}
public GameObject GetTrackingImage()
{
return ScannedImageObject;
}
//Adds the tracked values to building edge array
void AddToBuildingEdge(Vector2 coords)
{
edgesFound.Add(coords);
}
//Sets the pixel color stored in the multidimensional array for the tracked image
void SetPixelFillColor(Vector2 coord, Color32 newColor){
if (coord.x >= 0 && coord.x <= videoFootage.texture.width && coord.y >= 0 && coord.y <= videoFootage.texture.height)
{
//Store the pixel locally
imageColors[CoordToPixelArray(coord)] = newColor;
}
}
void SetPixelEdgeColor(Vector2 coord, Color32 newColor)
{
if (coord.x >= 0 && coord.x <= videoFootage.texture.width && coord.y >= 0 && coord.y <= videoFootage.texture.height)
{
//Store the pixel locally
imageColors[CoordToPixelArray(coord)] = newColor;
edgesFound.Add(coord);
if (debugDrawProgress)
{
RecolorImage();
}
}
}
//Used as a marker to block out portions of the image
void SetPixelMarkerColor(Vector2 coord, Color32 newColor)
{
if (coord.x > 0 && coord.x < videoFootage.texture.width && coord.y > 0 && coord.y < videoFootage.texture.height)
{
//Store the pixel locally
imageColors[CoordToPixelArray(coord)] = newColor;
}
}
//Gets the pixel color stored in the multidimensional array for the tracked image
Color32 GetPixelColor(Vector2 coord)
{
if (coord.x > 0 && coord.x < videoFootage.texture.width && coord.y > 0 && coord.y < videoFootage.texture.height)
{
return imageColors[CoordToPixelArray(coord)];
}
else{
//SetStatus("Off Screen at: " + coord);
return new Color32(0, 0, 0, 1); //This pixel is off the screen
}
}
public void DoRecognition()
{
//SetScale();
//GetAllColoredPixels();
if (!hasStartedProcess)
{
//Get the zoom level for google maps
//GoogleMap gMap = gameObject.GetComponent<GoogleMap>();
// if (gMap)
// {
zoomLevel = 19;// gMap.GetZoom();
mapSize = 512;// gMap.GetSize();
// }
hasStartedProcess = true;
SetStatus("Doing Recognition");
GetPoints();
}
}
void SetStatus(string newStatus)
{
//Make sure enough characters can be used per line
// char[] totalChars = newStatus.ToCharArray();
// charCount += totalChars.Length;
//accumStatus += "2";
accumStatus += newStatus + " | ";//\n";
// accumStatus = newStatus;
statusLabel.text = accumStatus;// "Status: " + newStatus + ".";
}
void AddBlob()
{
BlobData newBlob = new BlobData();
newBlob.name = "new object " + (blobData.Count + 1);
newBlob.edgesFound = new List<Vector2>(edgesFound); //List of all the edges for the current tracked building
newBlob.cornersFound = new List<Vector2>(cornersFound);
blobData.Add(newBlob);
UpdateBlobDetails();
}
public List<Vector2> GetFirstBlobCorners()
{
if (blobData.Count > 0)
return blobData[0].cornersFound;
else
return new List<Vector2>();
}
//Grabs a list of all the corners for every tracked object
public List<TracedBuildingType> GetAllObjectCorners(float scaleFactor)
{
List<TracedBuildingType> allBuildings = new List<TracedBuildingType>();
for (int i = 0; i < blobData.Count; i++)
{
TracedBuildingType newBuilding = new TracedBuildingType();
newBuilding.name = blobData[i].name;
List<Vector2z> cornerPoints = new List<Vector2z>();
for (int k = 0; k < blobData[i].cornersFound.Count; k++)
{
cornerPoints.Add(new Vector2z(blobData[i].cornersFound[k].x * scaleFactor, blobData[i].cornersFound[k].y * scaleFactor));
}
newBuilding.cornerPoints = cornerPoints;
allBuildings.Add(newBuilding);
}
Debug.Log("Finished getting object corners");
return allBuildings;
}
void UpdateBlobDetails()
{
string curBlobStats = "Object Count:" + blobData.Count + "\n";
for (int i = 0; i < blobData.Count; i++)
{
curBlobStats += blobData[i].name + ", Corners:" + blobData[i].cornersFound.Count + "\n";
}
blobDetailLabel.text = curBlobStats;
}
void SetTrackingAsComplete()
{
string blobDetails = blobDetailLabel.text;
blobDetails += "\n Completed!! \n Now run mapity and transform the tracked images into 3D buildings.";
blobDetailLabel.text = blobDetails;
//--------------------------------------------------------------
//Debug all the building data
//--------------------------------------------------------------
for (int i = 0; i < blobData.Count; i++)
{
string curBuildingValue = blobData[i].name + ": ";
for (int k = 0; k < blobData[i].cornersFound.Count; k++){
curBuildingValue += blobData[i].cornersFound[k].ToString() + ",";
}
Debug.Log(curBuildingValue);
}
hasStartedProcess = false;
}
void GetPoints()
{
SetStatus("1. Getting Points");
step1 = true;
StartCoroutine(WaitBeforeStart());
}
void ClearArrays()
{
//---------------------------------------------
// Reset the temporary texture to work with
//---------------------------------------------
imageColors = new Color32[0];
Texture2D curTexture = videoFootage.texture as Texture2D;
imageColors = curTexture.GetPixels32();
SetStatus("Total Pixels: " + imageColors.Length);
//Clear out the arrays of stored vertices per building
cornersFound.Clear();
edgesFound.Clear();
hasStartedEdgeDetect = false;
doCornerCheckRoutine = true;
hasFoundNewObject = false;
}
//Process for searching image for pixels
IEnumerator WaitBeforeStart()
{
while (true)
{
if (step1)
{
step1 = false;
ClearArrays();
SetStatus("Locating the blob edges");
LocateBlobEdges();
}
if (step2)
{
step2 = false;
SetStatus("Step 2 activated");
SearchNextPixel(cornersFound[0]);
//StartCoroutine(SearchNextPixel(coordsFound[0]));
}
/*
if (step3) //should be step 3
{
step3 = false;
//Color the surrounding pixels to identify the pixel
for (int i = 0; i < coordsFound.Count; i++)
{
StartCoroutine(ColorSurroundingPixels(coordsFound[i], 4));
}
}*/
if (step4)
{
step4 = false;
SetStatus("Filling Polygon");
StartCoroutine(FillPolygon());
}
yield return new WaitForSeconds(0.3f);
}
}
/** Getting pixel data in a coroutine causes a freeze, takes way too long, must be in standard function */
void LocateBlobEdges()
{
//For every color that isn't black, recolor it with yellow
Color32 pixel_color = new Color(0f, 0f, 0f, 1);
Color MarkerColor = new Color(1f, .4f, 1f);
Texture2D curImage = (Texture2D)videoFootage.texture;
SetStatus("Locating the blobs");
//Goes through every pixel and gets their color, checks the color against the tracking color
int imageWidth = curImage.width;
int imageHeight = curImage.height;
SetStatus("Grabbing Pixel colors");
//------------------------------------------------------------
//
// Grab all the image pixel colors and put them into an array
//
//------------------------------------------------------------
//Go through all the pixels in the image
for (int curIndex = 0; curIndex < imageColors.Length; curIndex++)
//for (int curIndex = 0; curIndex < 100; curIndex++)
{
Vector2 currentCoordinate = arrayToXYCoord(curIndex);
pixel_color = GetPixelColor(currentCoordinate);
if (hasFoundNewObject)
return;
switch (curDetectionScheme)
{
case ImageDetectAlgorithm.corner:
// SetStatus("pixel_color:" + pixel_color + " buildingColor:" + buildingColor);
if (CompareColors(pixel_color, buildingColor, errorCorrect))
{
CheckMatchingColor(0, currentCoordinate);
if (matchingColorCount < 7) //Skip pixels that are in the center of a building that are surrounded by matching pixels
{
//Allow the routine to break after this cycle
hasFoundNewObject = true;
SetStatus("BUILDING FOUND! At: " + currentCoordinate.x + "," + currentCoordinate.y);
//Save the current coordinate as a corner point
cornersFound.Add(currentCoordinate);
//Create a color box to identify the current point as a corner
ColorSurroundingPixels(currentCoordinate, 2, EdgeColor);
//Activate the corner detection algorithm
step2 = true;
}
}
break;
case ImageDetectAlgorithm.fill:
if (CompareColors(pixel_color, buildingColor, errorCorrect))
{
SetPixelFillColor(currentCoordinate, Red);
}
break;
}
}
switch(curDetectionScheme){
case ImageDetectAlgorithm.fill:
RecolorImage();
break;
}
SetTrackingAsComplete();
}
//Color pixels within a range of pixel distance, will color the pixels surrounding the current pixel
void ColorSurroundingPixels(Vector2 basePixel, int pixelDistance)
{
Color32 newColor = new Color32(0, 0, 0, 1);
for (int i = 0; i < pixelDistance; i++)
{
SetPixelMarkerColor(GoRight(basePixel), newColor);
SetPixelMarkerColor(GoLeft(basePixel), newColor);
SetPixelMarkerColor(GoUp(basePixel), newColor);
SetPixelMarkerColor(GoDown(basePixel), newColor);
SetPixelMarkerColor(GoUpRight(basePixel), newColor);
SetPixelMarkerColor(GoDownRight(basePixel), newColor);
SetPixelMarkerColor(GoUpLeft(basePixel), newColor);
SetPixelMarkerColor(GoDownLeft(basePixel), newColor);
SetPixelMarkerColor(basePixel, newColor);
}
}
void ColorSurroundingPixels(Vector2 basePixel, int pixelDistance, Color32 colorType)
{
for (int i = 0; i < pixelDistance; i++)
{
SetPixelMarkerColor(GoRight(basePixel), colorType);
SetPixelMarkerColor(GoLeft(basePixel), colorType);
SetPixelMarkerColor(GoUp(basePixel), colorType);
SetPixelMarkerColor(GoDown(basePixel), colorType);
SetPixelMarkerColor(GoUpRight(basePixel), colorType);
SetPixelMarkerColor(GoDownRight(basePixel), colorType);
SetPixelMarkerColor(GoUpLeft(basePixel), colorType);
SetPixelMarkerColor(GoDownLeft(basePixel), colorType);
SetPixelMarkerColor(basePixel, colorType);
}
}
void ColorPixelsBetween(Vector2 startCoordinate, Vector2 endCoordinate)
{
for (int curY = (int)startCoordinate.y; curY < (int)endCoordinate.y; curY++)
{
//Fill all the pixels from the start coordinate to the end coordinate
SetPixelFillColor(new Vector2(startCoordinate.x, curY), Red);
}
}
IEnumerator FillPolygon()
{
SetStatus("Starting the Fill Procedure");
for (int i = 0; i < edgesFound.Count; i++)
{
Vector2 startCoordinate = edgesFound[i];
Vector2 endCoordinate = edgesFound[i];
//Need to compare the current pixel coord with each edge pixels and color all pixels between them
for (int j = 0; j < edgesFound.Count; j++)
{
//Make sure we are on the correct x position
if (edgesFound[j].x == startCoordinate.x)
{
//Determine if the coordinate is greater or less than the last point and store that
if (edgesFound[j].y < startCoordinate.y)
startCoordinate.y = edgesFound[j].y;
if (edgesFound[j].y > endCoordinate.y)
endCoordinate.y = edgesFound[j].y;
}
}
//Color the pixels between the current start and end points on each x position
ColorPixelsBetween(startCoordinate, endCoordinate);
}
//Apply the color to the image and then repeat the steps to process the next shape
RecolorImage();
SetStatus("Completed the fill procedure");
//Start the initial loop again..
step1 = true;
StopCoroutine("WaitBeforeStart");
//DoRecognition();
yield return 0;
}
//Shifts the starting check pixel based on the last direction
IEnumerator IdentifyCorners(Vector2 nextPixel)
{
bool hasStartedStep1 = false;
int pixelsDrawn = 0;
Vector2 startPos = nextPixel;
List<Vector2> checkEdges = new List<Vector2>();
Vector2 edgeDirection = Vector2.zero;
Vector2 initialEdgeDirection = Vector2.zero;
Vector2 trakPos = nextPixel;
Vector2 initHead = Vector2.zero;
SetStatus("Corner Routine at "+ nextPixel);
while (doCornerCheckRoutine)
{
if (!hasStartedStep1)
{
hasStartedStep1 = true;
int tempNextPos = lastSelectedPos - 2;
if (tempNextPos == -1)
tempNextPos = 7;
else if (tempNextPos == -2)
tempNextPos = 6;
else if (tempNextPos == -3)
tempNextPos = 5;
//Here we will determine the next search direction
int identicalPixelCount = GetEdgeBasedOnStart(nextPixel, buildingColor, tempNextPos);
//The new direction will now be based of the last direction
switch (curDirection)
{
case SearchDirection.up: nextPixel = GoUp(nextPixel);
lastSelectedPos = 0;
break;
case SearchDirection.upRight: nextPixel = GoUpRight(nextPixel);
lastSelectedPos = 1;
break;
case SearchDirection.right: nextPixel = GoRight(nextPixel);
lastSelectedPos = 2;
break;
case SearchDirection.downRight: nextPixel = GoDownRight(nextPixel);
lastSelectedPos = 3;
break;
case SearchDirection.down: nextPixel = GoDown(nextPixel);
lastSelectedPos = 4;
break;
case SearchDirection.downLeft: nextPixel = GoDownLeft(nextPixel);
lastSelectedPos = 5;
break;
case SearchDirection.left: nextPixel = GoLeft(nextPixel);
lastSelectedPos = 6;
break;
case SearchDirection.upLeft: nextPixel = GoUpLeft(nextPixel);
lastSelectedPos = 7;
break;
}
if (debugDrawProgress)
{
SetPixelFillColor(nextPixel,new Color32(1,0,1,1));
RecolorImage();
}
//Try to close the loop
pixelsDrawn++;
if (checkEdges.Count < 4)
{
//Add the pixel to an array for corner detection
checkEdges.Add(nextPixel);
Vector2 cPoint = trakPos;
Vector2 nPoint = nextPixel;
initHead = nPoint - cPoint;
initialEdgeDirection = initHead / initHead.magnitude;
}
else
{
//Create point between current and next
Vector2 cPoint = trakPos;
Vector2 nPoint = nextPixel;
//Attributes of the two points
Vector2 head = nPoint - cPoint;
//Get the distance between the first and second point
float dist = head.magnitude;
float degR = Vector2.Angle(cPoint, nPoint);
edgeDirection = head / dist;
float diff = Vector2.Distance(initialEdgeDirection, edgeDirection);
//--------------------------------------------------
//Setting corners based on radius of cornerMinRadius
//-----------------------------------------------------------
if (Mathf.Abs(diff) > cornerMinRadius) //.4 too little, .6 too high
{
cornersFound.Add(nextPixel);
checkEdges.Clear();
}
trakPos = nextPixel;
}
//--------------------------------------
//Step 2:
//Setup edge outline
//--------------------------------------
if (identicalPixelCount > 0)
{
hasStartedEdgeDetect = true;
SetPixelEdgeColor(nextPixel, Green);
}
if ( totalErrors > 3){
totalErrors = 0;
SetStatus("Can't track this object...");
doCornerCheckRoutine = false; //Close the loop
//Apply the tracking data to the image for visualization
RecolorImage();
step4 = true; //Start filling the polygon
yield break;
}
//---------------------------------------------------------------
// Allow polygon completion check routine to be run
// only after 9 pixels have been drawn
//---------------------------------------------------------------
if (pixelsDrawn > 9)
{
//Attributes of the two points
Vector2 heading = nextPixel - startPos;
//Get the distance between the first and second point
float distance = heading.magnitude;
// Debug.Log("distance: " + distance);
if (distance < searchDistance)
{
SetStatus("Distane is less than " + searchDistance);
//Only called after a start and end point has been made, temporary...
if (hasStartedEdgeDetect)
{
hasStartedEdgeDetect = false;
SetStatus("Completed the building");
//Verify Close off the building edges
for (int i = 0; i < 3; i++)
{
//The new direction will now be based of the last direction
switch (curDirection)
{
case SearchDirection.up: nextPixel = GoUp(nextPixel);
lastSelectedPos = 0;
break;
case SearchDirection.upRight: nextPixel = GoUpRight(nextPixel);
lastSelectedPos = 1;
break;
case SearchDirection.right: nextPixel = GoRight(nextPixel);
lastSelectedPos = 2;
break;
case SearchDirection.downRight: nextPixel = GoDownRight(nextPixel);
lastSelectedPos = 3;
break;
case SearchDirection.down: nextPixel = GoDown(nextPixel);
lastSelectedPos = 4;
break;
case SearchDirection.downLeft: nextPixel = GoDownLeft(nextPixel);
lastSelectedPos = 5;
break;
case SearchDirection.left: nextPixel = GoLeft(nextPixel);
lastSelectedPos = 6;
break;
case SearchDirection.upLeft: nextPixel = GoUpLeft(nextPixel);
lastSelectedPos = 7;
break;
}
SetPixelEdgeColor(nextPixel, Green);
}
//-----------------------------------------------------------------
// Color all the corners
//-----------------------------------------------------------------
for (int i = 2; i < cornersFound.Count; i++)
{
SetStatus("Found corner @: " + cornersFound[i]);
ColorSurroundingPixels(cornersFound[i], 20, EdgeColor);
}
//Output the edge coordinates
//Debug.Log(coordList);
SetStatus("Completed tracking an object.");
AddBlob();
doCornerCheckRoutine = false; //Close the loop
//Apply the tracking data to the image for visualization
RecolorImage();
step4 = true; //Start filling the polygon
yield break;
}
}
}
hasStartedStep1 = false; //Allow loop for current procedure
}
else
{
SetStatus("Searching...");
}
yield return 0;
}
yield return 0;
}
void SearchNextPixel(Vector2 basePixel)
{
Vector2 nextPixel = basePixel;
SetStatus("Start identifying polygon");
StartCoroutine(IdentifyCorners(nextPixel));
}
void ClearMarks()
{
mark1 = false;
mark2 = false;
mark3 = false;
mark4 = false;
mark5 = false;
mark6 = false;
mark7 = false;
mark8 = false;
mark9 = false;
upperHalfCount = 0;
lowerHalfCount = 0;
}
void CheckMatchingColor(int curPos, Vector2 baseCoord)
{
Color searchColor = buildingColor;
matchingColorCount = 0;
if (CompareColors(GetPixelColor(GoUp(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.up;
matchingColorCount++;
}
if (CompareColors(GetPixelColor(GoUpRight(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.upRight;
matchingColorCount++;
}
if (CompareColors(GetPixelColor(GoRight(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.right;
matchingColorCount++;
}
if (CompareColors(GetPixelColor(GoDownRight(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.downRight;
matchingColorCount++;
}
if (CompareColors(GetPixelColor(GoDown(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.down;
matchingColorCount++;
}
if (CompareColors(GetPixelColor(GoDownLeft(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.downLeft;
matchingColorCount++;
}
if (CompareColors(GetPixelColor(GoLeft(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.left;
matchingColorCount++;
}
if (CompareColors(GetPixelColor(GoUpLeft(baseCoord)), searchColor, matchingColorErrorCorrect))
{
hasSetNextDirection = true;
curDirection = SearchDirection.upLeft;
matchingColorCount++;
}
// return null;
}
int GetEdgeBasedOnStart(Vector2 baseCoord, Color32 baseColor, int lastPos)
{
int identicalPixelCount = 0;
ClearMarks();
bool hasSetDirection = false;
int totalDirection = 8;
int incrementer = 0;
for (int i = lastPos; incrementer < totalDirection; i++)
{
incrementer++;
if (i > totalDirection)
i = 0;
switch (i)
{
case 0:
if (baseCoord.y < videoFootage.texture.height)
{
if (CompareColors(GetPixelColor(GoUp(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.up;
}
upperHalfCount++;
mark2 = true;
}
}
else
{
//"We are on the top edge");
// hasSetDirection = true;
// curDirection = SearchDirection.right;
totalErrors++;
//identicalPixelCount = 9;
}
break;
case 1:
if (baseCoord.y < videoFootage.texture.height && baseCoord.x < videoFootage.texture.width)
{
if (CompareColors(GetPixelColor(GoUpRight(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.upRight;
}
upperHalfCount++;
mark3 = true;
}
}
else
{
//("We are on the top edge or top right corner");
// hasSetDirection = true;
// curDirection = SearchDirection.down;
totalErrors++;
// identicalPixelCount = 9;
}
break;
case 2:
if (baseCoord.x < videoFootage.texture.width)
{
if (CompareColors(GetPixelColor(GoRight(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.right;
}
upperHalfCount++;
mark4 = true;
}
}
else
{
totalErrors++;
}
break;
case 3:
if (baseCoord.x < videoFootage.texture.width && baseCoord.y > 0)
{
if (CompareColors(GetPixelColor(GoDownRight(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.downRight;
}
upperHalfCount++;
mark5 = true;
}
}
else
{
totalErrors++;
}
break;
case 4:
if (baseCoord.y > 0)
{
if (CompareColors(GetPixelColor(GoDown(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.down;
}
upperHalfCount++;
mark6 = true;
}
}
else
{
totalErrors++;
}
break;
case 5:
if (baseCoord.y > 0 && baseCoord.x > 0)
{
if (CompareColors(GetPixelColor(GoDownLeft(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.downLeft;
}
lowerHalfCount++;
mark7 = true;
}
}
else
{
totalErrors++;
}
break;
case 6:
if (baseCoord.x > 0)
{
if (CompareColors(GetPixelColor(GoLeft(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.left;
}
lowerHalfCount++;
mark8 = true;
}
}
else
{
totalErrors++;
}
break;
case 7:
if (baseCoord.x > 0 && baseCoord.y < videoFootage.texture.height)
{
if (CompareColors(GetPixelColor(GoUpLeft(baseCoord)), baseColor, 2))
{
identicalPixelCount++;
if (!hasSetDirection)
{
hasSetDirection = true;
curDirection = SearchDirection.upLeft;
}
lowerHalfCount++;
mark1 = true;
}
}
else
{
totalErrors++;
}
break;
}
}
hasSetDirection = false;
return identicalPixelCount;
}
void FinishedColoringEdges()
{
Debug.Log("Finished Coloring");
}
Vector2 GoRight(Vector2 basePixel)
{
return new Vector2(basePixel.x + 1, basePixel.y);
}
Vector2 GoLeft(Vector2 basePixel)
{
return new Vector2(basePixel.x - 1, basePixel.y);
}
Vector2 GoUp(Vector2 basePixel)
{
return new Vector2(basePixel.x, basePixel.y + 1);
}
Vector2 GoDown(Vector2 basePixel)
{
return new Vector2(basePixel.x, basePixel.y - 1);
}
//Corner pixels
Vector2 GoUpRight(Vector2 basePixel)
{
return new Vector2(basePixel.x + 1, basePixel.y + 1);
}
Vector2 GoDownRight(Vector2 basePixel)
{
return new Vector2(basePixel.x + 1, basePixel.y - 1);
}
Vector2 GoUpLeft(Vector2 basePixel)
{
return new Vector2(basePixel.x - 1, basePixel.y + 1);
}
Vector2 GoDownLeft(Vector2 basePixel)
{
return new Vector2(basePixel.x - 1, basePixel.y - 1);
}
void RecolorImage()
{
//SetStatus("ColoringPixels");
Texture2D cloned = new Texture2D(videoFootage.texture.width, videoFootage.texture.height);
cloned.SetPixels32(imageColors);
cloned.Apply(false);
videoFootage.texture = cloned;
// SetStatus("FinishedColoringPixels");
}
//Checks whether 2 colors are similar, within a specified range
bool CompareColors(Color32 pixelColor, Color32 checkColor, int tempEfficiency)
{
float efficiency = tempEfficiency;// / 255;
if ((checkColor.r + efficiency) >= pixelColor.r && (checkColor.r - efficiency) <= pixelColor.r)
{
if ((checkColor.g + efficiency) >= pixelColor.g && (checkColor.g - efficiency) <= pixelColor.g)
{
if ((checkColor.b + efficiency) >= pixelColor.b && (checkColor.b - efficiency) <= pixelColor.b)
{
return true;
}
else
return false;
}
else
return false;
}
return false;
}
Mesh CreateMesh(int num)
{
int x = 0; //Counter
//Create a new mesh
Mesh mesh = new Mesh();
List<Vector3> vertices = new List<Vector3>();
for (int i = 0; i < cornersFound.Count; i++)
{
vertices.Add(Camera.main.ScreenToWorldPoint(new Vector3(cornersFound[i].x, cornersFound[i].y, Camera.main.nearClipPlane))); //new Vector3(coordsFound[i].x, coordsFound[i].y, 1));
}
//UVs
var uvs = new Vector2[cornersFound.Count];
for (x = 0; x < cornersFound.Count; x++)
{
if ((x % 2) == 0)
{
uvs[x] = new Vector2(0, 0);
}
else
{
uvs[x] = new Vector2(1, 1);
}
}
//Triangles
var tris = new int[3 * (vertices.Count - 2)]; //3 verts per triangle * num triangles
int C1;
int C2;
int C3;
num = 0;
if (num == 0)
{
C1 = 0;
C2 = 1;
C3 = 2;
for (x = 0; x < tris.Length; x += 3)
{
tris[x] = C1;
tris[x + 1] = C2;
tris[x + 2] = C3;
C2++;
C3++;
}
}
else
{
C1 = 0;
C2 = vertices.Count - 1;
C3 = vertices.Count - 2;
for (x = 0; x < tris.Length; x += 3)
{
tris[x] = C1;
tris[x + 1] = C2;
tris[x + 2] = C3;
C2--;
C3--;
}
}
//Assign data to mesh
mesh.vertices = vertices.ToArray();
mesh.uv = uvs;
mesh.triangles = tris;
//Recalculations
mesh.RecalculateNormals();
mesh.RecalculateBounds();
mesh.Optimize();
//Name the mesh
mesh.name = "MyMesh";
//Return the mesh
return mesh;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment