need a Method to return a variable Texturebrush. The method need to be overloaded with:
Size AreaSize,
int HorizontalSeperatorCount,
int VerticalSeperatorCount,
int SeperatorWidth,
Brush Seperatorbackground,
Brush Rectanglebackground,
The size of the rectangle will be calculated automatically
These example have following values
Size AreaSize = new Size(100, 100),
int HorizontalSeperatorCount = 1,
int VerticalSeperatorCount = 1,
int SeperatorWidth = 10,
Brush Seperatorbackground = Brushes.Grey,
Brush Rectanglebackground = Brushes.Red
The second example have a different VerticalSeperatorCount
Size AreaSize = new Size(100, 100),
int HorizontalSeperatorCount = 1,
int VerticalSeperatorCount = 3,
int SeperatorWidth = 10,
Brush Seperatorbackground = Brushes.Grey,
Brush Rectanglebackground = Brushes.Red
The signatur of the method
public static TextureBrush GetTextureBrush(Size areaSize, int horizontalSeperator, int verticalSeperatorCount, int seperatorWidth, Brush seperatorBackground, Brush rectangleBackground)
The Texturebrush will be used to fill a window
I'm not the best at the drawing stuff.
I would be very very happy about a solution.
public static TextureBrush GetSeperatorBrush(Size areaSize,
int horizontalSeperatorCount,
int verticalSeperatorCount,
int seperatorWidth,
Brush rectangleBackground)
{
var horizontalRectangleCount = horizontalSeperatorCount + 1.0f;
var verticalRectangleCount = verticalSeperatorCount + 1.0f;
var horizontalSeperatorBreadths = (horizontalSeperatorCount + 2.0f) * seperatorWidth;
var verticalSeperatorBreadths = (verticalSeperatorCount + 2.0f) * seperatorWidth;
var rectangleWidth = (areaSize.Width - verticalSeperatorBreadths) / verticalRectangleCount;
var rectangleHeight = (areaSize.Height - horizontalSeperatorBreadths) / horizontalRectangleCount;
var bitmap = new Bitmap((int)Math.Ceiling(rectangleWidth + seperatorWidth), (int)Math.Ceiling(rectangleHeight + seperatorWidth));
var graphics = Graphics.FromImage(bitmap);
var rectanglePoints = new[] { new PointF(seperatorWidth, seperatorWidth),
new PointF(seperatorWidth + rectangleWidth, seperatorWidth),
new PointF(seperatorWidth + rectangleWidth, seperatorWidth + rectangleHeight),
new PointF(seperatorWidth, seperatorWidth + rectangleHeight),
new PointF(seperatorWidth, seperatorWidth)};
graphics.FillPolygon(rectangleBackground, rectanglePoints);
graphics.Dispose();
var textureBrush = new TextureBrush(bitmap, System.Drawing.Drawing2D.WrapMode.Tile);
return textureBrush;
}
Make some trouble with to much seperators because of the rounding . It's ok for me.
Related
I'm working on pedestrians detection algorithm and got stuck on using ConnectedComponentsWithStats() method. I can't get to the values of stats. Here is what I wrote so far:
var labels = new Mat();
var stats = new Mat();
var centroids = new Mat();
var nLabels = CvInvoke.ConnectedComponentsWithStats(greyImage, labels, stats, centroids);
var centroidPoints = new MCvPoint2D64f[nLabels];
centroids.CopyTo(centroidPoints);
foreach (MCvPoint2D64f point in centroidPoints)
{
var x = point.X;
var y = point.Y;
}
The stats are stored as int32's in opencv c++ and have 5 fields x,y,width,height and area.
You can see the opencv implementation of ConnectedComponentsWithStats here.
Also you can see the struct CCStatsOp opencv returns the stats as here.
Sadly EMGUCV has not created the data structure CCStatsOp so you will need to just store the raw integer data like such.
int[] statsData = new int[stats.Rows * stats.Cols];
stats.CopyTo(statsData);
for (int i = 0; i < stats.Rows; i++)
{
var x = statsData[i * stats.Cols + 0];
var y = statsData[i * stats.Cols + 1];
var width = statsData[i * stats.Cols + 2];
var height = statsData[i * stats.Cols + 3];
var area = statsData[i * stats.Cols + 4];
}
You can also roll your own CCStats op with this code here.
Struct
public struct CCStatsOp
{
public Rectangle Rectangle;
public int Area;
}
Code
var labels = new Mat();
var stats = new Mat();
var centroids = new Mat();
var nLabels = CvInvoke.ConnectedComponentsWithStats(greyImage, labels, stats, centroids);
var centroidPoints = new MCvPoint2D64f[nLabels];
centroids.CopyTo(centroidPoints);
CCStatsOp[] statsOp = new CCStatsOp[stats.Rows];
stats.CopyTo(statsOp);
foreach (var statop in statsOp)
{
Console.WriteLine($"Rectangle: {statop.Rectangle} Area: {statop.Area}");
}
I'm trying to create an application that receives a sequence of images by Spout but I can not figure out the exact logic to it ...
I've never worked with OpenGL so do not know much about the correct syntax ...
All information is from the help here and looks very well explained ... but I could not properly understand how to put this logic to work ...
https://github.com/matjacques/LightjamsSpout
Below is my code and all I get is just a static image ...
I'm getting the result of a Bitmap and putting in a PictureBox ...
How do I put these images in an OpenGL object type?
public Form1()
{
InitializeComponent();
try
{
string senderName = "";
var receiver = new LightjamsSpoutLib.LightjamsSpoutReceiver();
int nbSenders = receiver.NbSenders();
for (int t = 0; t < nbSenders; ++t)
{
string name; int w, h;
receiver.GetSenderInfo(t, out name, out w, out h);
lblConnection.Text = name;
senderName = name;
// can instanciate the object in any thread
LightjamsSpoutLib.GLContext m_glContext = new LightjamsSpoutLib.GLContext();
m_glContext.Create();
LightjamsSpoutLib.LightjamsSpoutReceiver m_receiver = new LightjamsSpoutLib.LightjamsSpoutReceiver();
// the senderName as retrieved when enumerating senders or "" to use the active sender
int m_width = 500;
int m_height = 500;
m_receiver.Connect(senderName, out m_width, out m_height);
Bitmap m_bitmap = new Bitmap(m_width, m_height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
const int bytesPerPixel = 3;
int stride = 4 * ((m_width * bytesPerPixel + 3) / 4);
byte[] m_buffer = new byte[stride * m_height];
var data = m_bitmap.LockBits(new Rectangle(0, 0, m_width, m_height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
m_receiver.ReceiveImageIntPtr((long)data.Scan0, LightjamsSpoutLib.EPixelFormat.BGR);
m_bitmap.UnlockBits(data);
// Put in PictureBox (Only Static)
PictureBox Screen = new PictureBox();
Screen.Height = m_height;
Screen.Width = m_width;
Screen.Image = m_bitmap;
this.Controls.Add(Screen);
}
}
catch (System.Runtime.InteropServices.COMException e)
{
}
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I'm currently working on an exercise for my c# class. I am having some trouble with one particular part and would really appreciate some help.
I am working on an exercise in which we are given an incomplete project file.
The project has multiple classes, this class is for controlling squares that are placed on the board.
namespace HareAndTortoise {
public partial class SquareControl : PictureBox {
public const int SQUARE_SIZE = 100;
private Square square; // A reference to the corresponding square object
private BindingList<Player> players; // References the players in the overall game.
private bool[] containsPlayers = new bool[6];//HareAndTortoiseGame.MAX_PLAYERS];
public bool[] ContainsPlayers {
get {
return containsPlayers;
}
set {
containsPlayers = value;
}
}
// Font and brush for displaying text inside the square.
private Font textFont = new Font("Microsoft Sans Serif", 8);
private Brush textBrush = Brushes.White;
public SquareControl(Square square, BindingList<Player> players) {
this.square = square;
this.players = players;
// Set GUI properties of the whole square.
Size = new Size(SQUARE_SIZE, SQUARE_SIZE);
Margin = new Padding(0); // No spacing around the cell. (Default is 3 pixels.)
Dock = DockStyle.Fill;
BorderStyle = BorderStyle.FixedSingle;
BackColor = Color.CornflowerBlue;
SetImageWhenNeeded();
}
private void SetImageWhenNeeded()
{
if (square is Square.Win_Square)
{
LoadImageFromFile("Win.png");
textBrush = Brushes.Black;
}
else if (square is Square.Lose_Square)
{
LoadImageFromFile("Lose.png");
textBrush = Brushes.Red;
}
else if (square is Square.Chance_Square)
{
LoadImageFromFile("monster-green.png");
}
else if (square.Name == "Finish")
{
LoadImageFromFile("checkered-flag.png");
}
else
{
// No image needed.
}
}
private void LoadImageFromFile(string fileName) {
Image image = Image.FromFile(#"Images\" + fileName);
Image = image;
SizeMode = PictureBoxSizeMode.StretchImage; // Zoom is also ok.
}
protected override void OnPaint(PaintEventArgs e) {
// Due to a limitation in WinForms, don't use base.OnPaint(e) here.
if (Image != null)
e.Graphics.DrawImage(Image, e.ClipRectangle);
string name = square.Name;
// Create rectangle for drawing.
float textWidth = textFont.Size * name.Length;
float textHeight = textFont.Height;
float textX = e.ClipRectangle.Right - textWidth;
float textY = e.ClipRectangle.Bottom - textHeight;
RectangleF drawRect = new RectangleF(textX, textY, textWidth, textHeight);
// When debugging this method, show the drawing-rectangle on the screen.
//Pen blackPen = new Pen(Color.Black);
//e.Graphics.DrawRectangle(blackPen, textX, textY, textWidth, textHeight);
// Set format of string.
StringFormat drawFormat = new StringFormat();
drawFormat.Alignment = StringAlignment.Far; // Right-aligned.
// Draw string to screen.
e.Graphics.DrawString(name, textFont, textBrush, drawRect, drawFormat);
// Draw player tokens (when any players are on this square).
const int PLAYER_TOKENS_PER_ROW = 3;
const int PLAYER_TOKEN_SIZE = 30; // pixels.
const int PLAYER_TOKEN_SPACING = (SQUARE_SIZE - (PLAYER_TOKEN_SIZE * PLAYER_TOKENS_PER_ROW)) / (PLAYER_TOKENS_PER_ROW - 1);
for (int i = 0; i < containsPlayers.Length; i++) {
if (containsPlayers[i]) {
int xPosition = i % PLAYER_TOKENS_PER_ROW;
int yPosition = i / PLAYER_TOKENS_PER_ROW;
int xPixels = xPosition * (PLAYER_TOKEN_SIZE + PLAYER_TOKEN_SPACING);
int yPixels = yPosition * (PLAYER_TOKEN_SIZE + PLAYER_TOKEN_SPACING);
Brush playerTokenColour = players[i].PlayerTokenColour;
e.Graphics.FillEllipse(playerTokenColour, xPixels, yPixels, PLAYER_TOKEN_SIZE, PLAYER_TOKEN_SIZE);
}
}//endfor
}
}
}
The program trips up at:
else if (square.Name == "Finish")
{
LoadImageFromFile("checkered-flag.png");
}
I know it is because of square.name but from going through the code, I cant see why square.Name is not recognizable.
Square is passed from another class using this method
private void SetUpGuiGameBoard()
{
for (int i = 0; i <= 55; i++)
{
Square q = Board.GetGameBoardSquare(i);
SquareControl sq = new SquareControl(q, null);
int coloumn;
int row;
if (i == 0)
{
BackColor = Color.BurlyWood;
}
if (i == 55)
{
BackColor = Color.BurlyWood;
}
MapSquareNumToTablePanel(i, out coloumn, out row);
tableLayoutPanel1.Controls.Add(sq, coloumn, row);
}
and Squares are created in this class
private static Square[] gameBoard = new Square[56];
static public void SetUpBoard()
{
for (int i = 1; i == 55; i++)
{
gameBoard[i] = new Square("Ordinary Square", i);
}
gameBoard[0] = new Square("Start", 0);
gameBoard[4] = new Square.Lose_Square("Lose Square", 4);
gameBoard[5] = new Square.Chance_Square("Chance Square", 5);
gameBoard[9] = new Square.Win_Square("Win Square", 9);
gameBoard[11] = new Square.Chance_Square("Chance Square", 11);
gameBoard[14] = new Square.Lose_Square("Lose Square", 14);
gameBoard[17] = new Square.Chance_Square("Chance Square", 17);
gameBoard[19] = new Square.Win_Square("Win Square", 19);
gameBoard[24] = new Square.Lose_Square("Lose Square", 24);
gameBoard[29] = new Square.Win_Square("Win Square", 29);
gameBoard[34] = new Square.Lose_Square("Lose Square", 34);
gameBoard[35] = new Square.Chance_Square("Chance Square", 35);
gameBoard[39] = new Square.Win_Square("Win Square", 39);
gameBoard[44] = new Square.Lose_Square("Lose Square", 44);
gameBoard[47] = new Square.Chance_Square("Chance Square", 47);
gameBoard[49] = new Square.Win_Square("Win Square", 49);
gameBoard[53] = new Square.Chance_Square("Chance Square", 53);
gameBoard[55] = new Square("Finish", 56);
}
public static Square GetGameBoardSquare(int n)
{
return gameBoard[n];
}
public static Square StartSquare()
{
return gameBoard[0];
}
public static Square NextSquare(int n)
{
return gameBoard[(n+1)];
}
}
The answer already provided is the best way for prevention of any null reference exception. For more clarification I can suggest you to check the call stack at the point the debugger reaches the SquareControl constructor. At this point you should check why the Square object being passed in is a 'NULL'. That will lead you to the root cause of the problem. Hope this helps.
I'm using DrawingContext.DrawText and DrawingContext.PushTransfrom to create rotated text on Visual Layer in WPF but as you see in the image below, the rotated text is rather blurry in some areas of the image..
Is there any option I can use to improve this? The Arial font is used for the text.
public class BeamTextDrawing : FrameworkElement
{
private readonly VisualCollection _visuals;
public BeamTextDrawing(double scale)
{
if (scale <= 0)
{
scale = 1;
}
var typeface = Settings.BeamTextTypeface;
var cultureinfo = Settings.CultureInfo;
var flowdirection = Settings.FlowDirection;
var textsize = Settings.BeamTextSize / scale;
var beamtextcolor = Settings.InPlanBeamTextColor;
_visuals = new VisualCollection(this);
foreach (var beam in Building.BeamsInTheElevation)
{
var drawingVisual = new DrawingVisual();
using (var dc = drawingVisual.RenderOpen())
{
var text = Convert.ToString(beam.Section.Id);
//text = scale.ToString();
var ft = new FormattedText(text, cultureinfo, flowdirection,
typeface, textsize, beamtextcolor)
{
TextAlignment = TextAlignment.Center
};
var x1 = beam.ConnectivityLine.I.X;
var y1 = beam.ConnectivityLine.I.Y;
var x2 = beam.ConnectivityLine.J.X;
var y2 = beam.ConnectivityLine.J.Y;
var v1 = new Point(x2, y2) - new Point(x1, y1);
var v2 = new Vector(1, 0);
var hwidth = textsize;
var l = Geometrics.GetOffset(x1, y1, x2, y2, hwidth + 5/scale);
var angle = Vector.AngleBetween(v1, v2);
var x = 0.5 * (l.X1 + l.X2);
var y = 0.5 * (l.Y1 + l.Y2);
var r = new RotateTransform(angle, x, SelectableModel.FlipYAxis(y));
dc.PushTransform(r);
dc.DrawText(ft, SelectableModel.FlipYAxis(x, y));
}
_visuals.Add(drawingVisual);
}
}
protected override Visual GetVisualChild(int index)
{
return _visuals[index];
}
protected override int VisualChildrenCount
{
get
{
return _visuals.Count;
}
}
}
Update:
Here is the image after using this code:
TextOptions.SetTextFormattingMode(this, TextFormattingMode.Display);
I'm still getting blurry results. Look at the middle beam text at the lower part of the image.
You can change the TextFormattingMode to prevent blurry text:
public BeamTextDrawing(double scale)
{
TextOptions.SetTextFormattingMode(this, TextFormattingMode.Display);
// .. Your other code
So what I'm trying to do is take the Kinect Skeletal Sample and save x amount of photos, only when a human goes by. I have gotten it to work, except once it detects a human it just records x amount of photos even once the person leaves the vision of Kinect. Does anyone know how to make it so that once a person enters it starts recording, and once they leave it stops?
Variables
Runtime nui;
int totalFrames = 0;
int totalFrames2 = 0;
int lastFrames = 0;
int lastFrameWithMotion = 0;
int stopFrameNumber = 100;
DateTime lastTime = DateTime.MaxValue;
Entering/Exiting the Frame
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
SkeletonFrame skeletonFrame = e.SkeletonFrame;
int iSkeleton = 0;
++totalFrames;
string bb1 = Convert.ToString(totalFrames);
//Uri uri1 = new Uri("C:\\Research\\Kinect\\Proposal_Skeleton\\Skeleton_Img" + bb1 + ".png");
Uri uri1 = new Uri("C:\\temp\\Skeleton_Img" + bb1 + ".png");
// string file_name_3 = "C:\\Research\\Kinect\\Proposal_Skeleton\\Skeleton_Img" + bb1 + ".png"; // xxx
Brush[] brushes = new Brush[6];
brushes[0] = new SolidColorBrush(Color.FromRgb(255, 0, 0));
brushes[1] = new SolidColorBrush(Color.FromRgb(0, 255, 0));
brushes[2] = new SolidColorBrush(Color.FromRgb(64, 255, 255));
brushes[3] = new SolidColorBrush(Color.FromRgb(255, 255, 64));
brushes[4] = new SolidColorBrush(Color.FromRgb(255, 64, 255));
brushes[5] = new SolidColorBrush(Color.FromRgb(128, 128, 255));
skeleton.Children.Clear();
//byte[] skeletonFrame32 = new byte[(int)(skeleton.Width) * (int)(skeleton.Height) * 4];
foreach (SkeletonData data in skeletonFrame.Skeletons)
{
if (SkeletonTrackingState.Tracked == data.TrackingState)
{
// Draw bones
Brush brush = brushes[iSkeleton % brushes.Length];
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.Spine, JointID.ShoulderCenter, JointID.Head));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.ShoulderCenter, JointID.ShoulderLeft, JointID.ElbowLeft, JointID.WristLeft, JointID.HandLeft));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.ShoulderCenter, JointID.ShoulderRight, JointID.ElbowRight, JointID.WristRight, JointID.HandRight));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.HipLeft, JointID.KneeLeft, JointID.AnkleLeft, JointID.FootLeft));
skeleton.Children.Add(getBodySegment(data.Joints, brush, JointID.HipCenter, JointID.HipRight, JointID.KneeRight, JointID.AnkleRight, JointID.FootRight));
// Draw joints
// try to add a comment, xxx
foreach (Joint joint in data.Joints)
{
Point jointPos = getDisplayPosition(joint);
Line jointLine = new Line();
jointLine.X1 = jointPos.X - 3;
jointLine.X2 = jointLine.X1 + 6;
jointLine.Y1 = jointLine.Y2 = jointPos.Y;
jointLine.Stroke = jointColors[joint.ID];
jointLine.StrokeThickness = 6;
skeleton.Children.Add(jointLine);
}
// ExportToPng(uri1, skeleton);
// SoundPlayerAction Source = "C:/LiamScienceFair/muhaha.wav";
//SoundPlayer player1 = new SoundPlayer("muhaha.wav")
// player1.Play();
// MediaPlayer.
// axWindowsMediaPlayer1.currentPlaylist = axWindowsMediaPlayer1.mediaCollection.getByName("mediafile");
nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_ColorFrameReady2);
}
iSkeleton++;
} // for each skeleton
}
Actual Code
void nui_ColorFrameReady2(object sender, ImageFrameReadyEventArgs e)
{
// 32-bit per pixel, RGBA image xxx
PlanarImage Image = e.ImageFrame.Image;
int deltaFrames = totalFrames - lastFrameWithMotion;
if (totalFrames2 <= stopFrameNumber & deltaFrames > 300)
{
++totalFrames2;
string bb1 = Convert.ToString(totalFrames2);
// string file_name_3 = "C:\\Research\\Kinect\\Proposal\\Depth_Img" + bb1 + ".jpg"; xxx
string file_name_4 = "C:\\temp\\Video2_Img" + bb1 + ".jpg";
video.Source = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
BitmapSource image4 = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
image4.Save(file_name_4, Coding4Fun.Kinect.Wpf.ImageFormat.Jpeg);
if (totalFrames2 == stopFrameNumber)
{
lastFrameWithMotion = totalFrames;
stopFrameNumber += 100;
}
}
}
In most setups I have used in the skeletal tracking event area there is a check for if (skeleton != null) all you need to do is reset your trigger once a null skeleton is received.
The SDK will send a skeleton frame every time the event is fired so...
if(skeleton != null)
{
\\do image taking here
}
else
{
\\reset image counter
}
I would try something like this. Create a bool class variable named SkeletonInFrame and initialize it to false. Every time SkeletonFrameReady fires, set this bool to true. When you process a color frame, only process if this variable is true. Then after you process a color frame, set the variable to false. This should help you stop processing frame when you are no longer receiving skeleton events.