private static int loadShader(ShaderType type, string shaderCode) { // create a vertex shader type (GLES20.GL_VERTEX_SHADER) // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) int shader = GL.CreateShader(type); // add the source code to the shader and compile it string[] code = { shaderCode }; int[] length = { shaderCode.Length }; GL.ShaderSource(shader, 1, code, length); GL.CompileShader(shader); GLHelper.GetError(); int result = (int)All.True; GL.GetShader(shader, ShaderParameter.CompileStatus, out result); if (result == (int)All.False) { int logLength = 0; GL.GetShader(shader, ShaderParameter.InfoLogLength, out logLength); System.Text.StringBuilder info = new System.Text.StringBuilder(logLength); GL.GetShaderInfoLog(shader, logLength, out logLength, info); Console.WriteLine("Shader compile failed:" + info); return(0); } return(shader); }
public static void drawRect(RectangleF rect, Vector4 color, Matrix4 MVPMatrix) { float x = rect.X; float y = rect.Y; float width = rect.Width; float height = rect.Height; float[] Vertices = { x + width, y, x + width, y + height, x, y, x, y + height }; AmbientShader shader = AmbientShader.Singleton; // Use shader shader.Use(); shader.SetColor(color); shader.SetMVPMatrix(MVPMatrix); shader.EnableVertices(2, VertexAttribPointerType.Float, false, 0, Vertices); GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); shader.DisableVertices(); GLHelper.GetError(); }
// Should be called from GL thread public void RenderUpdate(RectangleF rect) { if (bSetupGL) { bSetupGL = false; SetupGL(); countLayerContext.SetupGL(); } if (bUpdateImage) { bUpdateImage = false; if (SetupImageTexture != null) { SetupImageTexture(imageTexName, out imageSize); } countLayerContext.OnImageUpdated(); } countLayerContext.RenderUpdate(rect); if (countLayerContext.Selection != null) { Vector2 selectCenter = CountLayerContext.Selection.GetCenter(); Vector4 selectPos = Vector4.Transform(new Vector4(selectCenter.X, selectCenter.Y, 0, 1), modelViewMatrix); ShowZoom(zoomTexName, zoomBuffer, selectPos, rect.Height, projectionMatrix, zoomOffset); } GLHelper.GetError(); }
public static void DrawSprite(uint texId, Rectangle rect, Matrix4 mat, float[] texCoords, Vector4 colorScale) { float x = rect.X; float y = rect.Y; float width = rect.Width; float height = rect.Height; float[] Vertices = { x + width, y, x + width, y + height, x, y, x, y + height }; if (texCoords == null) { float[] tx = { 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; texCoords = tx; } GLHelper.GetError(); TextureShader shader = TextureShader.Singleton; // Use shader GL.UseProgram(shader.mProgram); shader.SetColorScale(colorScale); // Set texture GL.ActiveTexture(TextureUnit.Texture0); // Set active texture slot to 0 GL.BindTexture(TextureTarget.Texture2D, texId); // Bind 2D texture to current slot GL.Uniform1(shader.muTextureHandle, 0); // Set shader sampler to texture slot 0 // 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, texCoords); GL.DrawArrays(BeginMode.TriangleStrip, 0, 4); GL.DisableVertexAttribArray(shader.maPositionHandle); GL.DisableVertexAttribArray(shader.maTexCoordHandle); GLHelper.GetError(); }
public void SetupGL() { // get an id from OpenGL GLHelper.GetError(); GL.GenTextures(1, out roiTexName); GL.GenTextures(1, out roiMaskTexName); GL.GenTextures(1, out maskTexName); GL.GenTextures(1, out thresholdTexName); GL.GenTextures(1, out debugTexName); GL.GenFramebuffers(1, out frameBuffer); GLHelper.GetError(); debugTexture = new MutableTexture(debugTexName); }
public static void setupTexture(uint texName, SizeF size, IntPtr data) { GL.BindTexture(TextureTarget.Texture2D, texName); GLHelper.GetError(); SetDefaultTexParameters(); GLHelper.GetError(); // generate the OpenGL texture GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)size.Width, (int)size.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data); GLHelper.GetError(); GL.BindTexture(TextureTarget.Texture2D, 0); GLHelper.GetError(); }
private static void readPixelsToTexture(Rectangle rect, uint texName, IntPtr buffer) { GL.ReadPixels(rect.X, rect.Y, rect.Width, rect.Height, PixelFormat.Rgba, PixelType.UnsignedByte, buffer); GLHelper.GetError(); GL.BindTexture(TextureTarget.Texture2D, texName); GLHelper.GetError(); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, rect.Width, rect.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, buffer); GL.BindTexture(TextureTarget.Texture2D, 0); GLHelper.GetError(); }
public static int createProgram(String vertexShaderCode, String fragmentShaderCode) { GLHelper.GetError(); int vertexShader = loadShader(ShaderType.VertexShader, vertexShaderCode); int fragmentShader = loadShader(ShaderType.FragmentShader, fragmentShaderCode); int mProgram = GL.CreateProgram(); // create empty OpenGL Program GL.AttachShader(mProgram, vertexShader); // add the vertex shader to program GL.AttachShader(mProgram, fragmentShader); // add the fragment shader to program GL.LinkProgram(mProgram); // creates OpenGL program executables GLHelper.GetError(); return(mProgram); }
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(); }
private void ShowZoom(uint texName, IntPtr buffer, Vector4 selectPos, float viewHeight, Matrix4 projMatrix, int offsetY) { // GL has inverted y axis Vector2 invertSelectPos = new Vector2(selectPos.X, viewHeight - selectPos.Y); Rectangle readRect = new Rectangle((int)selectPos.X - zoomSize.Width / 2, (int)invertSelectPos.Y - zoomSize.Height / 2, zoomSize.Width, zoomSize.Height); Rectangle drawRect = new Rectangle((int)selectPos.X - zoomSize.Width / 2, (int)selectPos.Y - zoomSize.Height / 2 + offsetY + zoomSize.Height, zoomSize.Width, -zoomSize.Height); readPixelsToTexture(readRect, texName, buffer); GLHelper.DrawSprite(texName, drawRect, projMatrix, null, Vector4.One); // Draw edge float[] Vertices = { drawRect.X, drawRect.Y, drawRect.X + drawRect.Width, drawRect.Y, drawRect.X + drawRect.Width, drawRect.Y + drawRect.Height, drawRect.X, drawRect.Y + drawRect.Height }; GL.LineWidth(2); GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.SrcColor); AmbientShader shader = AmbientShader.Singleton; shader.Use(); shader.SetColor(new Vector4(0.2f, 0.2f, 0.2f, 0.7f)); shader.SetMVPMatrix(projMatrix); shader.EnableVertices(2, VertexAttribPointerType.Float, false, 0, Vertices); GL.DrawArrays(BeginMode.LineLoop, 0, 4); shader.DisableVertices(); GL.LineWidth(1); }
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]); }
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]); }
public CountLayerContext(CCContext ccContext) { this.ccContext = ccContext; this.unitSphereVertices = GLHelper.CreateSphereVertices(Vector2.Zero, 1.0f, true); }
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]); }
public static void DrawROI(RectangleF viewRect, Vector2 vROICenter, float fROIRadius, Rectangle roiRect, uint roiMaskTexName, Vector4 outlineColor, float outlineWidth, Vector4 bgColor, Matrix4 MVMatrix, Matrix4 PMatrix) { Matrix4 MVPMatrix = MVMatrix * PMatrix; GL.Enable(EnableCap.Blend); { GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); // GL.BlendFunc(All.Zero, All.OneMinusSrcAlpha); GLHelper.DrawSprite(roiMaskTexName, roiRect, MVPMatrix, null, bgColor); } // Draw 4 areas outside ROI { Vector4 vTopLeft = Vector4.Transform(new Vector4(roiRect.X, roiRect.Y, 0, 1), MVMatrix); Vector4 vButtomRight = Vector4.Transform(new Vector4(roiRect.Right, roiRect.Bottom, 0, 1), MVMatrix); RectangleF boxRect; boxRect = RectangleF.Intersect(viewRect, new RectangleF(0, 0, viewRect.Width, vTopLeft.Y)); if (boxRect != RectangleF.Empty) { GLHelper.drawRect(boxRect, bgColor, PMatrix); } boxRect = RectangleF.Intersect(viewRect, new RectangleF(0, vButtomRight.Y, viewRect.Width, viewRect.Height - vButtomRight.Y)); if (boxRect != RectangleF.Empty) { GLHelper.drawRect(boxRect, bgColor, PMatrix); } boxRect = RectangleF.Intersect(viewRect, new RectangleF(0, vTopLeft.Y, vTopLeft.X, vButtomRight.Y - vTopLeft.Y)); if (boxRect != RectangleF.Empty) { GLHelper.drawRect(boxRect, bgColor, PMatrix); } boxRect = RectangleF.Intersect(viewRect, new RectangleF(vButtomRight.X, vTopLeft.Y, viewRect.Width - vButtomRight.X, vButtomRight.Y - vTopLeft.Y)); if (boxRect != RectangleF.Empty) { GLHelper.drawRect(boxRect, bgColor, PMatrix); } } GL.Disable(EnableCap.Blend); // ROI sphere { float r = fROIRadius; Vector2 pos = vROICenter; float[] vertices = GLHelper.CreateSphereVertices(pos, r, false); float oldLineWidth = 1; GL.GetFloat(GetPName.LineWidth, out oldLineWidth); GL.LineWidth(outlineWidth); AmbientShader shader = AmbientShader.Singleton; shader.Use(); shader.SetColor(outlineColor); shader.SetMVPMatrix(MVPMatrix); shader.EnableVertices(2, VertexAttribPointerType.Float, false, 0, vertices); GL.DrawArrays(BeginMode.LineLoop, 0, vertices.Length / 2); shader.DisableVertices(); GL.LineWidth(oldLineWidth); } }
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 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 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(); }
// Should be called from GL thread public void RenderUpdate(RectangleF rect) { //if (bUpdateImage) { // bUpdateImage = false; // Console.WriteLine("CountLayerContext UPDATE IMAGE"); // CCContext.setupTexture (maskTexName, ccContext.ImageSize, IntPtr.Zero); // int[] oldViewPort = new int[4]; // GL.GetInteger (GetPName.Viewport, oldViewPort); // GL.Viewport (0, 0, ccContext.ImageSize.Width, ccContext.ImageSize.Height); // int fboOld = GLHelper.bindFrameBuffer (frameBuffer, maskTexName); // // Clear texture // GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f); // GL.Clear (ClearBufferMask.ColorBufferBit); // // unbind framebuffer // GL.BindFramebuffer (FramebufferTarget.Framebuffer, fboOld); // GL.Viewport (oldViewPort [0], oldViewPort [1], oldViewPort [2], oldViewPort [3]); // bUpdateROI = true; // bUpdateROIThreshold = true; // bUpdateSeqmentation = true; //} //if (bUpdateROI) { // bUpdateROI = false; // Console.WriteLine("CountLayerContext UPDATE ROI"); // UpdateROI(); // bUpdateROIThreshold = true; //} List <Tag> tagsCopy = null; lock (tags) { tagsCopy = new List <Tag>(tags); } //if (bLateUpdateSegmentation) { // bLateUpdateSegmentation = false; // Console.WriteLine("CountLayerContext LATE UPDATE SEGMENTATION"); // // End running calc region task // if (cCalcRegionTokenSource != null) { // cCalcRegionTokenSource.Cancel (); // calcRegionTask = null; // } // if(bUpdateROIThreshold && tagsCopy.Count == 0) // { // CountLayerHelper.GetROIThreshold(roiRect, segmentationPixelData, roiThresholdMin, roiThresholdMax, frameBuffer, roiTexName); // bUpdateROIThreshold = false; // } // CountLayerHelper.UpdateThresholds (tagsCopy, roiRect, frameBuffer, roiTexName); // GLHelper.GetError (); // // Stop region task // CountLayerHelper.UpdateSegmentation (tagsCopy, roiRect, frameBuffer, thresholdTexName, roiTexName, // segmentationPixelData, roiThresholdMin, roiThresholdMax); // GLHelper.GetError (); // // Start calc region task // regions.Clear(); // incommingRegions.Clear(); // CountLayerHelper.SCalcRegionTask calcRegionTaskData = new CountLayerHelper.SCalcRegionTask (); // calcRegionTaskData.pixelData = segmentationPixelData; // calcRegionTaskData.roiRect = roiRect; // calcRegionTaskData.tags = tagsCopy.ToArray(); // calcRegionTaskData.debugTexture = debugTexture; // calcRegionTaskData.debugTexture.Clear (); // calcRegionTaskData.bDebugDrawEDM = false; // calcRegionTaskData.bDebugDrawRegions = false; // calcRegionTaskData.startTime = DateTime.Now; // calcRegionTaskData.regions = new List<Region>(); // calcRegionTaskData.regionAdded += delegate(object sender, EventArgs e) { // lock(incommingRegions) { // incommingRegions.Add (sender as Region); // }; // ccContext.RequestRender (); // // if (CountLayerUpdated != null) { // // CountLayerUpdated (tags.Count, regions.Count); // // } // }; // cCalcRegionTokenSource = new CancellationTokenSource (); // CancellationToken cToken = cCalcRegionTokenSource.Token; // calcRegionTask = Task.Factory.StartNew<CountLayerHelper.SCalcRegionTask> (() => CountLayerHelper.calcRegions (cToken, calcRegionTaskData), cToken); // calcRegionTask.ContinueWith (task => { // // Request render so we can get task result in render thread // ccContext.RequestRender (); // }); //} //// Handle incomming regions //lock(incommingRegions) { // if(incommingRegions.Count > 0) { // regions.AddRange(incommingRegions); // incommingRegions.Clear(); // } //}; //// Trigger segmentation update next frame //if(bUpdateSeqmentation) { // bUpdateSeqmentation = false; // bLateUpdateSegmentation = true; // Console.WriteLine("CountLayerContext UPDATE SEGMENTATION"); // ccContext.RequestRender (); //} //// Check calc region task //if (calcRegionTask != null && calcRegionTask.IsCompleted) { //calcRegionTaskComplete) // CountLayerHelper.SCalcRegionTask taskData = calcRegionTask.Result; // ICollection<Region> result = taskData.regions; // TimeSpan span = DateTime.Now.Subtract(taskData.startTime); // Console.WriteLine("CountLayerContext REGION RESULT (duration:"+span.TotalSeconds+")"); // regions.Clear (); // regions.AddRange (result); // calcRegionTask = null; // if (CountLayerUpdated != null) { // CountLayerUpdated (tagsCopy.Count, regions.Count); // } //} // RENDERING !!! // Clear background GLHelper.GetError(); GL.ClearColor(1.0f, 0.0f, 0.0f, 1); GLHelper.GetError(); GL.Clear(ClearBufferMask.ColorBufferBit); GLHelper.GetError(); Matrix4 mat = ccContext.ModelViewMatrix * ccContext.ProjectionMatrix; // Draw image { Rectangle imageRect = new Rectangle(0, 0, (int)ccContext.ImageSize.Width, (int)ccContext.ImageSize.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; // if (activeTool == Tool.ROIEdit) { // bool selected = selectedPrim != null && selectedPrim.GetPrimitive () == roiSphere; // outlineColor = selected ? ColorHelper.ColorToVec(ColorHelper.ROIEdgeSelected) : ColorHelper.ColorToVec(ColorHelper.ROIEdgeActive); // bgColor = ColorHelper.ColorToVec(ColorHelper.ROIBackgroundActive); // outlineWidth = 2; // } // CountLayerHelper.DrawROI (rect, roiSphere.center, roiSphere.radius, roiRect, roiMaskTexName, outlineColor, outlineWidth, bgColor, ccContext.ModelViewMatrix, ccContext.ProjectionMatrix); //} // // Draw debug texture // bool bDragDebugTexture = false; // if (bDragDebugTexture) { // debugTexture.prepareForRender (); //// GLHelper.DrawSprite(debugTexName, roiRect, mat); //// GLHelper.DrawSprite(roiTexName, roiRect, mat); // GLHelper.DrawSprite (roiMaskTexName, roiRect, mat); // } //{ // CountLayerHelper.DrawRegions (regions, ccContext.ModelViewMatrix, ccContext.ProjectionMatrix); //} // Draw tags { Tag selectedTag = selectedPrim != null?selectedPrim.GetPrimitive() as Tag : null; bool layerActive = activeTool == Tool.TagCreate || activeTool == Tool.TagDelete; float tagSize = ccContext.TagSize; CountLayerHelper.drawTags(tagsCopy, selectedTag, layerActive, ccContext.ModelViewMatrix, ccContext.ProjectionMatrix, tagSize); } if (bRequestSaveImage) { bRequestSaveImage = false; CreateSaveImage(tagsCopy); } }