//==================== DISTANCE MAPPING STUFF ====================// private void ComputeDistanceMaps(BlobData gt) { int CORE = 0; int NEW = -1; var gtpl = gt.pixels.Length; gt.distOut = new int[gtpl]; gt.distIn = new int[gtpl]; for (int i = 0; i < gtpl; i++) { var gtm = gt.pixels[i] != 0; gt.distOut[i] = gtm ? CORE : NEW; gt.distIn[i] = gtm ? NEW : CORE; } var w = _canvas.width; RemapFlaggedIntArrayAsDepth(ref gt.distOut, w, 0, distanceFactor); RemapFlaggedIntArrayAsDepth(ref gt.distIn, w, 0, distanceFactor); }
private void ContinuePaint(Vector2 position) { // Check to make sure last texture coordinate is set to a reasonable value. if (_lastTexCoord.x == -50000 || _lastTexCoord.y == -50000) { return; } var positions = new List <Vector2>(); var gap = Vector2.Distance(_lastTexCoord, position) * (_canvas.width + _canvas.height) * 0.5f; if (gap > minGap) { int times = Mathf.FloorToInt(gap / minGap); // Increment only the maximum number of times for gaps. if (times > maxGapIncrements) { times = maxGapIncrements; } for (float i = 1; i < times; i++) { positions.Add(Vector2.Lerp(_lastTexCoord, position, i / times)); } } positions.Add(position); var ci = GetCurrentIndex(); BlobData userBlob = GetUserBlobForIndex(ci); var affectedIndices = new List <int>(); foreach (var pos in positions) { foreach (var ai in DoStrokeAt(pos, ci, userBlob)) { if (!affectedIndices.Contains(ai)) { affectedIndices.Add(ai); } } } _canvas.Apply(); var userMarkups = new List <MarkupBase>(); foreach (var index in affectedIndices) { var affBlob = GetUserBlobForIndex(index); affBlob.center = GetWeightedBlobCenter(ref affBlob.pixels, _canvas.width); if (affBlob.center.x < -49000) { _userBlobs.Remove(index); } else { userMarkups.Add(affBlob); } } if (!mystery) { UpdateMarkupPercents(userMarkups); } }
private List <int> DoStrokeAt(Vector2 position, int ci, BlobData userBlob) { HashSet <int> ret = new HashSet <int>(); if (!_painting && !_erasing) { return(ret.ToList()); } if (!_erasing) { ret.Add(ci); } int cw = _canvas.width; int ch = _canvas.height; float px = position.x * cw; float py = position.y * ch; int rw = Mathf.FloorToInt(_radius * cw); int rh = Mathf.FloorToInt(_radius * ch); int cx = Mathf.FloorToInt(px - rw * 0.5f); int cy = Mathf.FloorToInt(py + rh * 0.5f); float avgR = (Mathf.Max(rw, rh)) / 4f; var color = _color; if (!_erasing) { var colorWiggle = UIMgr.Instance.colorWiggle; color = color - new Color(UnityEngine.Random.Range(0, colorWiggle), UnityEngine.Random.Range(0, colorWiggle), UnityEngine.Random.Range(0, colorWiggle), 0); } var avgRSquared = avgR * avgR; // TODO: convert this to run on getpixels/setpixels jfc lol int l = _indices.Length; for (int x = cx; x < cx + rw; x++) { for (int y = cy; y >= cy - rh; y--) { // Faster to compare squared distances. if ((px - x) * (px - x) + (py - y) * (py - y) < avgRSquared) { _canvas.SetPixel(x, y, color); var pos = y * cw + x; if (pos >= 0 && pos < l) { var old = _indices[pos]; if (old > 0) { if (_erasing && _tempOld < 0) { _tempOld = old; } GetUserBlobForIndex(old).pixels[pos] = 0; // Can add at will since hashset by default does not allow for duplicates. ret.Add(old); } _indices[pos] = ci; if (_painting && userBlob != null) { userBlob.pixels[pos] = ci; } } } } } return(ret.ToList()); }
override protected IEnumerator ParseGroundTruths() { var groundTruthTex2D = GameMgr.CurrentGroundTruthTex2D(); if (groundTruthTex2D == null) { Debug.LogError("no image for ground truth generation"); yield break; } //compute is slow, this updates app status first DebugText.instance.Log("Generating distance maps..."); yield return(null); _groundTruthBlobs = new Dictionary <int, BlobData>(); //pre-process image to extract indices from the pixels var gt = groundTruthTex2D; if (gt == null) { DebugText.instance.Log("ERROR: could not find ground truth"); yield break; } var gtPixels = gt.GetPixels32(); var gp = gt.width * gt.height; var gtIndices = new int[gp]; for (int i = 0; i < gp; i++) { gtIndices[i] = gtPixels[i].r; } int blobIndex = 0; int safety = 0; int rolling = 0; while (safety++ < 500) { //get the first non-zero index var pos = -1; for (; rolling < gp; rolling++) { if (gtIndices[rolling] > 0) { pos = rolling; break; } } if (pos < 0) { DebugText.instance.Log("SUCCESS: loaded ground truth"); break; } // Get all connected indices var index = gtIndices[pos]; if (index <= 0) { DebugText.instance.Log("ERROR: problem loading ground truth"); break; } // Just build a mask by scanning the image, don't lasso at all BlobData blob = new BlobData(gt.width, gt.height, index); for (int i = 0; i < blob.pixels.Length; i++) { if (gtIndices[i] == index) { blob.pixels[i] = index; gtIndices[i] = 0; } else { blob.pixels[i] = 0; } } blob.Resize(); blobIndex++; blob.center = GetWeightedBlobCenter(ref blob.pixels, gt.width); ComputeDistanceMaps(blob); _groundTruthBlobs.Add(index, blob); } }