public static void updateROIImage(Rectangle roiRect, uint frameBuffer, uint imageTexName, Size imageSize, uint roiTexName, uint roiMaskTexName) { GLHelper.GetError(); // Setup viewport int[] oldViewPort = new int[4]; GL.GetInteger(GetPName.Viewport, oldViewPort); GL.Viewport(0, 0, roiRect.Size.Width, roiRect.Size.Height); int fboOld = GLHelper.bindFrameBuffer(frameBuffer, roiTexName); // Render to source texture float left = (float)roiRect.Location.X / (float)imageSize.Width; float right = (float)(roiRect.Location.X + roiRect.Size.Width) / (float)imageSize.Width; float top = (float)roiRect.Location.Y / (float)imageSize.Height; float button = (float)(roiRect.Location.Y + roiRect.Size.Height) / (float)imageSize.Height; // NB: texture coords are mirrored vertically float[] texCoords = { right, top, right, button, left, top, left, button }; // Render source Matrix4 mat = Matrix4.CreateOrthographicOffCenter(0, (float)roiRect.Size.Width, 0, (float)roiRect.Size.Height, -1.0f, 1.0f); Rectangle r = new Rectangle(0, 0, roiRect.Width, roiRect.Height); GLHelper.DrawSprite(imageTexName, r, mat, texCoords, Vector4.One); // Render mask onto source GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.Zero, BlendingFactorDest.OneMinusSrcAlpha); GLHelper.DrawSprite(roiMaskTexName, r, mat); GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.Zero); GL.Disable(EnableCap.Blend); // unbind framebuffer GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboOld); GL.Viewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]); GLHelper.GetError(); }
public static void updateROIMask(Rectangle roiRect, Size imageSize, uint frameBuffer, uint roiMaskTexName, uint maskTexName) { GLHelper.GetError(); // Setup viewport int[] oldViewPort = new int[4]; GL.GetInteger(GetPName.Viewport, oldViewPort); GL.Viewport(0, 0, roiRect.Size.Width, roiRect.Size.Height); int fboOld = GLHelper.bindFrameBuffer(frameBuffer, roiMaskTexName); // Fill with 1.1.1.1 GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit); GLHelper.GetError(); // Draw crop if (true) { float[] vertices = GLHelper.CreateSphereVertices(new Vector2((float)roiRect.Size.Width * 0.5f, (float)roiRect.Size.Height * 0.5f), (float)roiRect.Size.Height * 0.5f, true); // Set Model view Matrix4 MVPMatrix = Matrix4.CreateOrthographicOffCenter(0, (float)roiRect.Size.Width, 0, (float)roiRect.Size.Height, -1.0f, 1.0f); AmbientShader shader = AmbientShader.Singleton; shader.Use(); shader.SetColor(new Vector4(0, 0, 0, 0)); shader.SetMVPMatrix(MVPMatrix); shader.EnableVertices(2, VertexAttribPointerType.Float, false, 0, vertices); GLHelper.GetError(); GL.DrawArrays(BeginMode.TriangleFan, 0, vertices.Length / 2); shader.DisableVertices(); } // Draw mask if (true) { // Render to source texture float left = (float)roiRect.Location.X / (float)imageSize.Width; float right = (float)(roiRect.Location.X + roiRect.Size.Width) / (float)imageSize.Width; float top = (float)roiRect.Location.Y / (float)imageSize.Height; float button = (float)(roiRect.Location.Y + roiRect.Size.Height) / (float)imageSize.Height; // NB: texture coords are mirrored vertically float[] texCoords = { right, top, right, button, left, top, left, button }; Matrix4 mat = Matrix4.CreateOrthographicOffCenter(0, (float)roiRect.Size.Width, 0, (float)roiRect.Size.Height, -1.0f, 1.0f); Rectangle r = new Rectangle(0, 0, roiRect.Width, roiRect.Height); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GLHelper.DrawSprite(maskTexName, r, mat, texCoords, Vector4.One); GL.Disable(EnableCap.Blend); } // unbind framebuffer GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboOld); // Cleanup viewport GL.Viewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]); GLHelper.GetError(); }
static public void UpdateSegmentation(ICollection <Tag> tags, Rectangle roiRect, uint frameBuffer, uint thresholdTexName, uint roiTexName, uint[] segmentationPixelData, int[] roiThresholdMin, int[] roiThresholdMax) { float[] thresholdMin = { 1, 1, 1 }; float[] thresholdMax = { 0, 0, 0 }; if (tags.Count == 0) { thresholdMin = new float[] { (float)roiThresholdMin[0] / 255.0f, (float)roiThresholdMin[1] / 255.0f, (float)roiThresholdMin[2] / 255.0f }; thresholdMax = new float[] { (float)roiThresholdMax[0] / 255.0f, (float)roiThresholdMax[1] / 255.0f, (float)roiThresholdMax[2] / 255.0f }; } else { // TODO: use ALL thresholds foreach (Tag tag in tags) { float[] min = new float[3]; float[] max = new float[3]; tag.GetNormalizedMaxMin(ref min, ref max); thresholdMin[0] = Math.Min(thresholdMin[0], min[0]); thresholdMin[1] = Math.Min(thresholdMin[1], min[1]); thresholdMin[2] = Math.Min(thresholdMin[2], min[2]); thresholdMax[0] = Math.Max(thresholdMax[0], max[0]); thresholdMax[1] = Math.Max(thresholdMax[1], max[1]); thresholdMax[2] = Math.Max(thresholdMax[2], max[2]); // thresholdMin = new float[3] { min[0], min[1], min[2]}; // thresholdMax = new float[3] { max[0], max[1], max[2]}; Console.WriteLine("color:" + tag.Color[0] + "," + tag.Color[1] + "," + tag.Color[2]); } } // Setup thresholdTexName as framebuffer int[] oldViewPort = new int[4]; GL.GetInteger(GetPName.Viewport, oldViewPort); GL.Viewport(0, 0, roiRect.Size.Width, roiRect.Size.Height); int fboOld = GLHelper.bindFrameBuffer(frameBuffer, thresholdTexName); // Clear GL.ClearColor(1.0f, 0.0f, 0.0f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit); float x = 0; float y = 0; float width = roiRect.Size.Width; float height = roiRect.Size.Height; float[] Vertices = { x + width, y, x + width, y + height, x, y, x, y + height }; float[] Texture = { 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; Vector4 color = new Vector4(1, 1, 1, 1); Matrix4 mat = Matrix4.CreateOrthographicOffCenter(0, (float)roiRect.Size.Width, 0, (float)roiRect.Size.Height, -1.0f, 1.0f); ThresholdShader shader = ThresholdShader.Singleton; // Use shader shader.Use(); // Set texture shader.SetTexture(roiTexName); // Set threshold Vector4 vMin = new Vector4(thresholdMin[0], thresholdMin[2], thresholdMin[2], 1); Vector4 vMax = new Vector4(thresholdMax[0], thresholdMax[2], thresholdMax[2], 1); shader.SetThreshold(vMin, vMax); shader.setColor(color); // Set Model view GL.UniformMatrix4(shader.muMVPMatrixHandle, 1, false, ref mat.Row0.X); // Set vertex and texture coords GL.EnableVertexAttribArray(shader.maPositionHandle); GL.EnableVertexAttribArray(shader.maTexCoordHandle); GL.VertexAttribPointer(shader.maPositionHandle, 2, VertexAttribPointerType.Float, false, 0, Vertices); GL.VertexAttribPointer(shader.maTexCoordHandle, 2, VertexAttribPointerType.Float, false, 0, Texture); GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); GL.DisableVertexAttribArray(shader.maPositionHandle); GL.DisableVertexAttribArray(shader.maTexCoordHandle); // Read pixel data { GL.ReadPixels(0, 0, roiRect.Size.Width, roiRect.Size.Height, PixelFormat.Rgba, PixelType.UnsignedByte, segmentationPixelData); // GL.ReadPixels<uint>(0, 0, roiRect.Size.Width, roiRect.Size.Height, All.Rgba, All.UnsignedByte, segmentationPixelData); } // unbind framebuffer and cleanup viewport GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboOld); GL.Viewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]); }
public static void UpdateThresholds(ICollection <Tag> tags, Rectangle roiRect, uint frameBuffer, uint roiTexName) { // Setup resultTexName framebuffer int[] oldViewPort = new int[4]; GL.GetInteger(GetPName.Viewport, oldViewPort); GL.Viewport(0, 0, roiRect.Size.Width, roiRect.Size.Height); int fboOld = GLHelper.bindFrameBuffer(frameBuffer, roiTexName); float[] histR = new float[256]; float[] histG = new float[256]; float[] histB = new float[256]; // TODO: cache tag thresholds and only recalculate when dirty (otherwise many tags will impeede performance) if (tags.Count > 0) { // Rectangle localRoiRect = new Rectangle (0, 0, roiRect.Width, roiRect.Height); int sampleWidth = 100; int pixelCount = sampleWidth * sampleWidth; byte[] pixels = new byte[pixelCount * 4]; foreach (Tag tag in tags) { if (tag.calculateThreshold) { tag.calculateThreshold = false; Rectangle sampleRect = tag.ThresholdSampleRect; Point loc = sampleRect.Location; loc.Offset(-roiRect.Location.X, -roiRect.Location.Y); sampleRect.Location = loc; // sampleRect = Rectangle.Intersect(tagRect, localRoiRect); // Skip rects outside roi if (sampleRect.Width == 0 || sampleRect.Height == 0) { continue; } // Clear histograms for (int i = 0; i < 256; i++) { histR [i] = 0; histG [i] = 0; histB [i] = 0; } // Read pixels GL.ReadPixels(sampleRect.Left, sampleRect.Top, sampleRect.Width, sampleRect.Height, PixelFormat.Rgba, PixelType.UnsignedByte, pixels); // Get color of tag (center of sample) int pxIdx = pixelCount * 2 + sampleRect.Width * 2; tag.Color [0] = pixels [pxIdx] & 0xff; tag.Color [1] = pixels [pxIdx + 1] & 0xff; tag.Color [2] = pixels [pxIdx + 2] & 0xff; // Get histogram for pixels around tag int count = pixelCount * 4; int j = 0; while (j < count) { int iR = pixels [j++] & 0xff; int iG = pixels [j++] & 0xff; int iB = pixels [j++] & 0xff; int iA = pixels [j++] & 0xff; if (iA > 0) { histR [iR]++; histG [iG]++; histB [iB]++; } } // Fill gaps in threshold to prepare it for threshold finding Histogram.FillGaps(histR); Histogram.FillGaps(histG); Histogram.FillGaps(histB); // Find threshold tag.Threshold [0] = OtsuThreshold.getThreshold(histR); tag.Threshold [1] = OtsuThreshold.getThreshold(histG); tag.Threshold [2] = OtsuThreshold.getThreshold(histB); } } } // unbind framebuffer and cleanup viewport GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboOld); GL.Viewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]); }
public static void GetROIThreshold(Rectangle rect, uint[] pixelBuffer, int[] min, int[] max, uint frameBuffer, uint roiTexName) { // Setup viewport int[] oldViewPort = new int[4]; GL.GetInteger(GetPName.Viewport, oldViewPort); GL.Viewport(0, 0, rect.Size.Width, rect.Size.Height); int fboOld = GLHelper.bindFrameBuffer(frameBuffer, roiTexName); // Update ROI histogram // TODO: use already allocated segmentation buffer { float[] histR = new float[256]; float[] histG = new float[256]; float[] histB = new float[256]; int pixelCount = rect.Width * rect.Height; byte[] pixels = new byte[pixelCount * 4]; GL.ReadPixels(0, 0, rect.Width, rect.Height, PixelFormat.Rgba, PixelType.UnsignedByte, pixels); int count = pixelCount * 4; int j = 0; int sumR = 0, sumG = 0, sumB = 0; int sampleCount = 0; while (j < count) { int iR = pixels [j++] & 0xff; int iG = pixels [j++] & 0xff; int iB = pixels [j++] & 0xff; int iA = pixels [j++] & 0xff; if (iA > 0) { sampleCount++; sumR += iR; sumG += iG; sumB += iB; histR [iR]++; histG [iG]++; histB [iB]++; } } float avrR = (float)sumR / (float)sampleCount; // float avrG = (float)sumG/(float)sampleCount; // float avrB = (float)sumB/(float)sampleCount; Histogram.FillGaps(histR); Histogram.FillGaps(histG); Histogram.FillGaps(histB); // Find threshold int thresholdR = OtsuThreshold.getThreshold(histR); int thresholdG = OtsuThreshold.getThreshold(histG); int thresholdB = OtsuThreshold.getThreshold(histB); if (avrR > thresholdR) { min[0] = 0; min[1] = 0; min[2] = 0; max[0] = thresholdR; max[1] = thresholdG; max[2] = thresholdB; } else { min[0] = thresholdR; min[1] = thresholdG; min[2] = thresholdB; max[0] = 1; max[1] = 1; max[2] = 1; } } // unbind framebuffer GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboOld); GL.Viewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]); }
public static void MaskDraw(Vector2 pos, Vector2 prevPos, bool bForeground, uint frameBuffer, uint texName, Size texSize, float[] sphereVertices, int scale) { // FIXME: radius is in image space and needs to be dps adjusted // Setup viewport int[] oldViewPort = new int[4]; GL.GetInteger(GetPName.Viewport, oldViewPort); GL.Viewport(0, 0, texSize.Width, texSize.Height); int fboOld = GLHelper.bindFrameBuffer(frameBuffer, texName); Vector4 foreground = new Vector4(1, 1, 1, 1); Vector4 background = new Vector4(0, 0, 0, 0); Vector4 color = bForeground ? foreground : background; AmbientShader shader = AmbientShader.Singleton; shader.Use(); shader.SetColor(color); Matrix4 ProjMatrix = Matrix4.CreateOrthographicOffCenter(0, (float)texSize.Width, 0, (float)texSize.Height, -1.0f, 1.0f); // Draw sphere at pos { // Set Model view Matrix4 MVPMatrix = Matrix4.Scale(scale) * Matrix4.CreateTranslation(new Vector3(pos)) * ProjMatrix; shader.SetMVPMatrix(MVPMatrix); shader.EnableVertices(2, VertexAttribPointerType.Float, false, 0, sphereVertices); GLHelper.GetError(); GL.DrawArrays(BeginMode.TriangleFan, 0, sphereVertices.Length / 2); shader.DisableVertices(); } // Connect prev to current if (!pos.Equals(prevPos)) { shader.SetMVPMatrix(ProjMatrix); // shader.SetMVPMatrix(projMatrix); // Vector2 v0 = CCContext.ViewToModel(prevPos, modelViewMatrix); // Vector2 v1 = CCContext.ViewToModel(pos, modelViewMatrix); Vector2 v0 = prevPos; Vector2 v1 = pos; Vector3 up = new Vector3(0, 0, 1); Vector3 dir = new Vector3(v1) - new Vector3(v0); dir = Vector3.Normalize(dir); Vector3 cross = Vector3.Cross(up, dir) * scale; float[] vertices = new float[4 * 2]; int i = 0; vertices[i++] = v0.X - cross.X; vertices[i++] = v0.Y - cross.Y; vertices[i++] = v0.X + cross.X; vertices[i++] = v0.Y + cross.Y; vertices[i++] = v1.X - cross.X; vertices[i++] = v1.Y - cross.Y; vertices[i++] = v1.X + cross.X; vertices[i++] = v1.Y + cross.Y; shader.EnableVertices(2, VertexAttribPointerType.Float, false, 0, vertices); GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); // GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, 4); shader.DisableVertices(); } // unbind framebuffer GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboOld); GL.Viewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]); }
private void CreateSaveImage(ICollection <Tag> tagArray) { if (SaveCountResult == null) { return; } Size size = ccContext.ImageSize; uint outputTexName = 0; // Generate texture GL.GenTextures(1, out outputTexName); CCContext.setupTexture(outputTexName, size, IntPtr.Zero); // Setup viewport int[] oldViewPort = new int[4]; GL.GetInteger(GetPName.Viewport, oldViewPort); GL.Viewport(0, 0, size.Width, size.Height); int fboOld = GLHelper.bindFrameBuffer(frameBuffer, outputTexName); GL.Disable(EnableCap.Blend); Matrix4 projectionMatrix = Matrix4.CreateOrthographicOffCenter(0, (float)size.Width, 0, (float)size.Height, -1.0f, 1.0f); // Matrix4 projectionMatrix = ccContext.ProjectionMatrix; Matrix4 modelViewMatrix = Matrix4.Identity; // Draw image { Matrix4 mat = modelViewMatrix * projectionMatrix; Rectangle imageRect = new Rectangle(0, 0, (int)size.Width, (int)size.Height); GLHelper.DrawSprite(ccContext.ImageTexName, imageRect, mat); } // Draw ROI Vector4 outlineColor = ColorHelper.ColorToVec(ColorHelper.ROIEdge); Vector4 bgColor = ColorHelper.ColorToVec(ColorHelper.ROIBackground); float outlineWidth = 1.0f; RectangleF rect = new RectangleF(PointF.Empty, new SizeF(size)); CountLayerHelper.DrawROI(rect, roiSphere.center, roiSphere.radius, roiRect, roiMaskTexName, outlineColor, outlineWidth, bgColor, modelViewMatrix, projectionMatrix); // Regions CountLayerHelper.DrawRegions(regions, modelViewMatrix, projectionMatrix); // Draw tags { float tagSize = 16; CountLayerHelper.drawTags(tagArray, null, true, modelViewMatrix, projectionMatrix, tagSize); } // allocate array and read pixels into it. int myDataLength = size.Width * size.Height * 4; byte[] buffer = new byte[myDataLength]; GL.ReadPixels(0, 0, size.Width, size.Height, PixelFormat.Rgba, PixelType.UnsignedByte, buffer); // Call save image event SaveCountResult(buffer, size, tags.Count, regions.Count); buffer = null; GL.DeleteTextures(1, ref outputTexName); // unbind framebuffer GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboOld); GL.Viewport(oldViewPort[0], oldViewPort[1], oldViewPort[2], oldViewPort[3]); }