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.
Related
I am trying to create movie from images.
I am following following links :
https://www.leadtools.com/support/forum/posts/t11084- // Here I am trying option 2 mentioned & https://social.msdn.microsoft.com/Forums/sqlserver/en-US/b61726a4-4b87-49c7-b4fc-8949cd1366ac/visual-c-visual-studio-2017-how-do-you-convert-jpg-images-to-video-in-visual-c?forum=csharpgeneral
void convert()
{
bmp = new Bitmap(320, 240, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
// create sample source object
SampleSource smpsrc = new SampleSource();
ConvertCtrl convertCtrl = new ConvertCtrl();
// create a new media type wrapper
MediaType mt = new MediaType();
double AvgTimePerFrame = (10000000 / 15);
// set the type to 24-bit RGB video
mt.Type = Constants.MEDIATYPE_Video;
mt.SubType = Constants.MEDIASUBTYPE_RGB24;
// set the format
mt.FormatType = Constants.FORMAT_VideoInfo;
VideoInfoHeader vih = new VideoInfoHeader();
int bmpSize = GetBitmapSize(bmp);
// setup the video info header
vih.bmiHeader.biCompression = 0; // BI_RGB
vih.bmiHeader.biBitCount = 24;
vih.bmiHeader.biWidth = bmp.Width;
vih.bmiHeader.biHeight = bmp.Height;
vih.bmiHeader.biPlanes = 1;
vih.bmiHeader.biSizeImage = bmpSize;
vih.bmiHeader.biClrImportant = 0;
vih.AvgTimePerFrame.lowpart = (int)AvgTimePerFrame;
vih.dwBitRate = bmpSize * 8 * 15;
mt.SetVideoFormatData(vih, null, 0);
// set fixed size samples matching the bitmap size
mt.SampleSize = bmpSize;
mt.FixedSizeSamples = true;
// assign the source media type
smpsrc.SetMediaType(mt);
// select the LEAD compressor
convertCtrl.VideoCompressors.MCmpMJpeg.Selected = true;
convertCtrl.SourceObject = smpsrc;
convertCtrl.TargetFile = #"D:\Projects\LEADTool_Movie_fromImage\ImageToVideo_LeadTool\ImageToVideo_LeadTool\Images\Out\aa.avi";
//convertCtrl.TargetFile = "C:\\Users\\vipul.langalia\\Documents\\count.avi";
convertCtrl.TargetFormat = TargetFormatType.WMVMux;
convertCtrl.StartConvert();
BitmapData bmpData;
int i = 1;
byte[] a = new byte[bmpSize];
System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height);
var imgs = GetAllFiles();
foreach (var item in imgs)
{
bmpSize = GetBitmapSize(item);
MediaSample ms = smpsrc.GetSampleBuffer(30000);
ms.SyncPoint = true;
bmpData = item.LockBits(rect, ImageLockMode.ReadWrite, item.PixelFormat);
Marshal.Copy(bmpData.Scan0, a, 0, bmpSize);
item.UnlockBits(bmpData);
ms.SetData(bmpSize, a);
SetSampleTime(ms, i, AvgTimePerFrame);
smpsrc.DeliverSample(1000, ms);
i++;
}
smpsrc.DeliverEndOfStream(1000);
}
byte[] GetByteArrayFroMWritableBitmap(WriteableBitmap bitmapSource)
{
var width = bitmapSource.PixelWidth;
var height = bitmapSource.PixelHeight;
var stride = width * ((bitmapSource.Format.BitsPerPixel + 7) / 8);
var bitmapData = new byte[height * stride];
bitmapSource.CopyPixels(bitmapData, stride, 0);
return bitmapData;
}
private int GetBitmapSize(WriteableBitmap bmp)
{
int BytesPerLine = (((int)bmp.Width * 24 + 31) & ~31) / 8;
return BytesPerLine * (int)bmp.Height;
}
private int GetBitmapSize(Bitmap bmp)
{
int BytesPerLine = ((bmp.Width * 24 + 31) & ~31) / 8;
return BytesPerLine * bmp.Height;
}
It is throwing out of memory exception when execute ms.SetData(bmpSize, a); statement. Plus If I directly pass byte[] by var a = System.IO.File.ReadAllBytes(imagePath); in ms.SetData(bmpSize, a); statement then it will not throw error but video file is not properly created.
Can anybody please help me?
There are a couple of problems with your code:
Are all your images 320x240 pixels? If not, you should resize them to these exact dimensions before delivering them as video samples to the Convert control.
If you want to use a different size, you can, but it should be the same size for all images, and you should modify the code accordingly.
You are setting the TargetFormat property to WMVMux, but the name of the output file has “.avi” extension. If you want to save AVI files, set TargetFormat = TargetFormatType.AVI.
If you still face problems after this, feel free to contact support#leadtools.com and provide full details about what you tried and what errors you’re getting. Email support is free for LEADTOOLS SDK owners and also for free evaluation users.
I'm creatin a Code39 barcode image with C# and I need to add margin to this image.
This is the first image which I created.
I created it.
But it should be like this.
It should be like this.
The code is complicated.
This code is creating barcode bars, number and title strings.
public byte[] Code39(string code, int barSize, bool showCodeString, string title, string fontFile)
{
// Create stream....
MemoryStream ms = new MemoryStream();
FontFamilyName = "Free 3 of 9";//ConfigurationSettings.AppSettings["BarCodeFontFamily"];
FontFileName = fontFile;//#"C:\Documents and Settings\narottam.sharma\Desktop\Barcode\WSBarCode\Code39Font\FREE3OF9.TTF";// ConfigurationSettings.AppSettings["BarCodeFontFile"];
FontSize = barSize;
ShowCodeString = showCodeString;
if (title + "" != "")
Title = title;
Bitmap objBitmap = GenerateBarcode(code);
objBitmap.Save(ms, ImageFormat.Png);
//return bytes....
return ms.GetBuffer();
}
public Bitmap GenerateBarcode(string barCode)
{
int bcodeWidth = 0;
int bcodeHeight = 0;
// Get the image container...
Bitmap bcodeBitmap = CreateImageContainer(barCode, ref bcodeWidth, ref bcodeHeight);
Graphics objGraphics = Graphics.FromImage(bcodeBitmap);
// Fill the background
objGraphics.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, bcodeWidth, bcodeHeight));
int vpos = 0;
// Draw the title string
if (_titleString != null)
{
objGraphics.DrawString(_titleString, _titleFont, new SolidBrush(Color.Black), XCentered((int)_titleSize.Width, bcodeWidth), vpos);
vpos += (((int)_titleSize.Height) + _itemSepHeight);
}
// Draw the barcode
objGraphics.DrawString(barCode, Code39Font, new SolidBrush(Color.Black), XCentered((int)_barCodeSize.Width, bcodeWidth), vpos);
// Draw the barcode string
if (_showCodeString)
{
vpos += (((int)_barCodeSize.Height));
objGraphics.DrawString(barCode, _codeStringFont, new SolidBrush(Color.Black), XCentered((int)_codeStringSize.Width, bcodeWidth), vpos);
}
// return the image...
return bcodeBitmap;
}
private Bitmap CreateImageContainer(string barCode, ref int bcodeWidth, ref int bcodeHeight)
{
Graphics objGraphics;
// Create a temporary bitmap...
Bitmap tmpBitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
objGraphics = Graphics.FromImage(tmpBitmap);
// calculate size of the barcode items...
if (_titleString != null)
{
_titleSize = objGraphics.MeasureString(_titleString, _titleFont);
bcodeWidth = (int)_titleSize.Width;
bcodeHeight = (int)_titleSize.Height + _itemSepHeight;
}
_barCodeSize = objGraphics.MeasureString(barCode, Code39Font);
bcodeWidth = Max(bcodeWidth, (int)_barCodeSize.Width);
bcodeHeight += (int)_barCodeSize.Height;
if (_showCodeString)
{
_codeStringSize = objGraphics.MeasureString(barCode, _codeStringFont);
bcodeWidth = Max(bcodeWidth, (int)_codeStringSize.Width);
bcodeHeight += (_itemSepHeight + (int)_codeStringSize.Height);
}
// dispose temporary objects...
objGraphics.Dispose();
tmpBitmap.Dispose();
return (new Bitmap(bcodeWidth, bcodeHeight, PixelFormat.Format32bppArgb));
}
You can modify the objGraphics.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, bcodeWidth, bcodeHeight)); call from GenerateBarcode and make the width greater.
var margin = VALUE NEEDED;
objGraphics.FillRectangle(new SolidBrush(Color.White), new Rectangle(margin, 0, bcodeWidth + margin, bcodeHeight));
// Draw additiona text to the left
objGraphics.DrawString(ADDITIONAL_TEXT, _titleFont, new SolidBrush(Color.Black), new RectangleF(0, 0, margin, bcodeHeight)); //you can modify the rectangle area as needed
I have an application A that is made in WPF and WinForms.I have written another Application in WinForms for Capturing Screen. The problem I'm facing is that The dialog boxes that come up in Application A do not captured in the screen. The whole screen gets captured including the area behind the dialog box but the dialog box doesn't get captured.
public void CaptureScreen(string filepath)
{
string[] words = filepath.Split('\\');
string newFilePath = " ";
foreach (string word in words)
{
if (!(word.Contains(".bmp")))
{
newFilePath = newFilePath + word + "//";
}
else
{
newFilePath = newFilePath + word;
}
}
this.WindowState = FormWindowState.Minimized;
Screen[] screens;
screens = Screen.AllScreens;
int noofscreens = screens.Length, maxwidth = 0, maxheight = 0;
for (int i = 0; i < noofscreens; i++)
{
if (maxwidth < (screens[i].Bounds.X + screens[i].Bounds.Width)) maxwidth = screens[i].Bounds.X + screens[i].Bounds.Width;
if (maxheight < (screens[i].Bounds.Y + screens[i].Bounds.Height)) maxheight = screens[i].Bounds.Y + screens[i].Bounds.Height;
}
var width = maxwidth;
var height = maxheight;
Point sourcePoint = Point.Empty;
Point destinationPoint = Point.Empty;
Rectangle rect = new Rectangle(0, 0, width, height);
Bitmap bitmap = new Bitmap(rect.Width, rect.Height);
Graphics g = Graphics.FromImage(bitmap);
// g.CopyFromScreen(sourcePoint, destinationPoint, rect.Size);
g.CopyFromScreen(new Point(rect.Left, rect.Top), Point.Empty, rect.Size);
bitmap.Save(filepath, ImageFormat.Bmp);
//Console.WriteLine("(width, height) = ({0}, {1})", maxx - minx, maxy - miny);
}
}
}
Bitmap bmpScreenshot = new Bitmap(Screen.AllScreens[1].Bounds.Width, Screen.AllScreens[1].Bounds.Height, PixelFormat.Format32bppArgb);
Graphics.FromImage(bmpScreenshot).CopyFromScreen(
Screen.AllScreens[1].Bounds.X,
Screen.AllScreens[1].Bounds.Y,
0,
0,
Screen.AllScreens[1].Bounds.Size,
CopyPixelOperation.SourceCopy);
this.picExtendedModitorScreen.Image = bmpScreenshot;
this.picExtendedModitorScreen.Refresh();
Put this code in timer tick event.
I have put extended screen 1 in the code you can change it to any other.
DrawImage method of Graphics class is not creating high quality images. In this method I am splitting a master image into multiple image but the code generating first image in very low quality. But it is generating full black images for remaining height.
public static Bitmap[] Split(byte[] ByteImage)
{
// MasterImage: there is no problem in master image. it is saving it in good quality.
MemoryStream ms = new MemoryStream(ByteImage);
System.Drawing.Image MasterImage = System.Drawing.Image.FromStream(ms);
MasterImage.Save(HttpContext.Current.Server.MapPath("../../../App_Shared/Reports/Temp/MasterImage.Bmp"), ImageFormat.Bmp);
//Split master image into multiple image according to height / 1000
Int32 ImageHeight = 1000, ImageWidth = MasterImage.Width, MasterImageHeight = MasterImage.Height;
int PageCount = 0;
Int32 TotalPages = MasterImage.Height / 1000;
Bitmap[] imgs = new Bitmap[TotalPages];
for (int y = 0; y + 1000 < MasterImageHeight; y += 1000, PageCount++)
{
imgs[PageCount] = new Bitmap(ImageWidth, ImageHeight, PixelFormat.Format32bppPArgb);
using (Graphics gr = Graphics.FromImage(imgs[PageCount]))
{
gr.CompositingQuality = CompositingQuality.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.SmoothingMode = SmoothingMode.HighQuality;
//First image now working with this code line
gr.DrawImage(MasterImage, new System.Drawing.Rectangle(0, y, ImageWidth, ImageHeight),new System.Drawing.Rectangle(0, 0, ImageWidth, ImageHeight), GraphicsUnit.Pixel); //new System.Drawing.Rectangle(new Point(0, y), new Size(ImageWidth, ImageHeight)));
//gr.DrawImage(MasterImage, new System.Drawing.Rectangle(0, y, ImageWidth, ImageHeight)); //new System.Drawing.Rectangle(new Point(0, y), new Size(ImageWidth, ImageHeight)));
string FilePath = HttpContext.Current.Server.MapPath("../../../App_Shared/Reports/Temp/Image" + PageCount.ToString() + ".bmp");
imgs[PageCount].Save(FilePath, System.Drawing.Imaging.ImageFormat.Bmp);
//Here it is saving images. I got first image with very poor quality but remaining in total balck color.
gr.Dispose();
}
}
return imgs;
}
As #HansPassant mentioned the source and target rectangle are reversed.
You could also change the structure of your splitting a bit so it could work a bit more flexible, and it might have a better readability at a later time.
class Program
{
static IList<Bitmap> SplitImage(Bitmap sourceBitmap, int splitHeight)
{
Size dimension = sourceBitmap.Size;
Rectangle sourceRectangle = new Rectangle(0, 0, dimension.Width, splitHeight);
Rectangle targetRectangle = new Rectangle(0, 0, dimension.Width, splitHeight);
IList<Bitmap> results = new List<Bitmap>();
while (sourceRectangle.Top < dimension.Height)
{
Bitmap pageBitmap = new Bitmap(targetRectangle.Size.Width, sourceRectangle.Bottom < dimension.Height ?
targetRectangle.Size.Height
:
dimension.Height - sourceRectangle.Top, PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(pageBitmap))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
g.DrawImage(sourceBitmap, targetRectangle, sourceRectangle, GraphicsUnit.Pixel);
}
sourceRectangle.Y += sourceRectangle.Height;
results.Add(pageBitmap);
}
return results;
}
static void Main(string[] args)
{
string sourceFilename = Environment.CurrentDirectory + #"\testimage.jpg";
Bitmap sourceBitmap = (Bitmap)Image.FromFile(sourceFilename);
var images = SplitImage(sourceBitmap, 79);
int len = images.Count;
for (int x = len; --x >= 0; )
{
var bmp = images[x];
string filename = "Images-" + x + ".bmp";
bmp.Save(Environment.CurrentDirectory + #"\" + filename, ImageFormat.Bmp);
images.RemoveAt(x);
bmp.Dispose();
Console.WriteLine("Saved " + filename);
}
Console.WriteLine("Done with the resizing");
}
}
This would also dynamically size the last image in case the page is less than your specified bitmap height at the end :)
I copied the AForge-Sample from here:
http://www.aforgenet.com/framework/features/template_matching.html
And hoped, it would work with 2 Bitmaps as sources as in the following code:
Bitmap findTemplate (Bitmap sourceImage, Bitmap template)
{
// create template matching algorithm's instance
// (set similarity threshold to x.y%, 1.0f = 100%)
ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching( 0.4f );
// find all matchings with specified above similarity
TemplateMatch[] matchings = tm.ProcessImage( sourceImage, template ); **// "Unsupported pixel format of the source or template image." as error message**
// highlight found matchings
BitmapData data = sourceImage.LockBits(
new Rectangle( 0, 0, sourceImage.Width, sourceImage.Height ),
ImageLockMode.ReadWrite, sourceImage.PixelFormat );
foreach ( TemplateMatch m in matchings )
{
AForge.Imaging.Drawing.Rectangle( data, m.Rectangle, System.Drawing.Color.White );
// do something else with matching
}
sourceImage.UnlockBits( data );
return sourceImage;
}
But when calling TemplateMatch[] matchings = tm.P.... it gives the error mentioned above.
The template is generated this way:
Bitmap templatebitmap=(Bitmap)AForge.Imaging.Image.FromFile("template.jpg");
the source is generated with the kinect-webcam, where the PlanarImage is formatted as Bitmap (method copied from somewhere, but it was working up to now)
Bitmap PImageToBitmap(PlanarImage PImage)
{
Bitmap bmap = new Bitmap(
PImage.Width,
PImage.Height,
System.Drawing.Imaging.PixelFormat.Format32bppRgb);
BitmapData bmapdata = bmap.LockBits(
new Rectangle(0, 0, PImage.Width,
PImage.Height),
ImageLockMode.WriteOnly,
bmap.PixelFormat);
IntPtr ptr = bmapdata.Scan0;
Marshal.Copy(PImage.Bits,
0,
ptr,
PImage.Width *
PImage.BytesPerPixel *
PImage.Height);
bmap.UnlockBits(bmapdata);
return bmap;
}
So, is anbody able to help me, where my mistake might be?
Or maybe anyone knows a better way to match a template with a Kinect?
The overall job is to detect a known object with the kinect, in my case a rubberduck.
Thank you in advamce.
here's the solution using AForge
but it is slow take around 5 seconds but it works
As usuall u need to introduce AForge framework download and install it.
specify using AForge namespace
and copy paste to make it work
System.Drawing.Bitmap sourceImage = (Bitmap)Bitmap.FromFile(#"C:\SavedBMPs\1.jpg");
System.Drawing.Bitmap template = (Bitmap)Bitmap.FromFile(#"C:\SavedBMPs\2.jpg");
// create template matching algorithm's instance
// (set similarity threshold to 92.5%)
ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.921f);
// find all matchings with specified above similarity
TemplateMatch[] matchings = tm.ProcessImage(sourceImage, template);
// highlight found matchings
BitmapData data = sourceImage.LockBits(
new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
ImageLockMode.ReadWrite, sourceImage.PixelFormat);
foreach (TemplateMatch m in matchings)
{
Drawing.Rectangle(data, m.Rectangle, Color.White);
MessageBox.Show(m.Rectangle.Location.ToString());
// do something else with matching
}
sourceImage.UnlockBits(data);
So, I just implemented it myself. But it is so slow - so if anyone has an idea to improve, feel free to criticize my code:
public class Position
{
public int bestRow { get; set; }
public int bestCol { get; set; }
public double bestSAD { get; set; }
public Position(int row, int col, double sad)
{
bestRow = row;
bestCol = col;
bestSAD = sad;
}
}
Position element_position = new Position(0, 0, double.PositiveInfinity);
Position ownSearch(Bitmap search, Bitmap template) {
Position position = new Position(0,0,double.PositiveInfinity);
double minSAD = double.PositiveInfinity;
// loop through the search image
for (int x = 0; x <= search.PhysicalDimension.Width - template.PhysicalDimension.Width; x++)
{
for (int y = 0; y <= search.PhysicalDimension.Height - template.PhysicalDimension.Height; y++)
{
position_label2.Content = "Running: X=" + x + " Y=" + y;
double SAD = 0.0;
// loop through the template image
for (int i = 0; i < template.PhysicalDimension.Width; i++)
{
for (int j = 0; j < template.PhysicalDimension.Height; j++)
{
int r = Math.Abs(search.GetPixel(x + i, y + j).R - template.GetPixel(i, j).R);
int g = Math.Abs(search.GetPixel(x + i, y + j).G - template.GetPixel(i, j).G);
int b = Math.Abs(search.GetPixel(x + i, y + j).B - template.GetPixel(i, j).B);
int a = template.GetPixel(i, j).A;
SAD = SAD + ((r + g + b)*a/255 );
}
}
// save the best found position
if (minSAD > SAD)
{
minSAD = SAD;
// give me VALUE_MAX
position.bestRow = x;
position.bestCol = y;
position.bestSAD = SAD;
}
}
}
return position;
}