Below is the code for a method which I am using for detecting faces from Kinect Feed and then setting the pixels from the face into a new image. . It is triggered by a Gesture which is done by GestureFlag . The Detect method which I am calling from the FaceDetection class is taken from the EMGU CV sample.
public string Detect(WriteableBitmap colorBitmap, int GestureFlag)
{
if(GestureFlag!=0)
{
List<Rectangle> faces = new List<Rectangle>();
Bitmap bitface = BitmapFromSource(colorBitmap);
Image<Bgr, Byte> image = new Image<Bgr, Byte>(bitface);
FaceDetection.Detect(image, "haarcascade_frontalface_default.xml",faces);
Bitmap img = new Bitmap(#"C:\Users\rama\Downloads\kinect-2-background-removal-master\KinectBackgroundRemoval\Assets\emptyimage.png");
img = ResizeImage(img, 1540, 1980);
int high = image.Height;
int width = image.Width;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < high; j++)
{
Bgr pixel = image[j,i];
System.Drawing.Point p = new System.Drawing.Point(j,i);
if (faces[0].Contains(p) && i<1540 && j<1980)
{
img.SetPixel(i, j, System.Drawing.Color.FromArgb(255, (int)pixel.Blue, (int)pixel.Green,(int) pixel.Red));
}
}
}
count++;
key = count.ToString() + "rich.jpg";
image.Save(#"C:\Users\rama\Downloads\kinect-2-background-removal-master\KinectBackgroundRemoval\Assets\"+key);
img.Save(#"C:\Users\rama\Downloads\kinect-2-background-removal-master\KinectBackgroundRemoval\"+key);
bool status = UploadToS3("nitish2", key, #"C:\Users\rama\Downloads\kinect-2-background-removal-master\KinectBackgroundRemoval\"+key);
var FBClient = new FacebookClient();
var UploadToFacebook = new FacebookUpload(FBClient, key);
UploadToFacebook.Show();
GestureFlag = 0;
}
return key;
}
The problem I'm running into is that an entirely different set of pixels gets printed on the new image which I'm saving.
Basically i think that the problem is here:
FaceDetection.Detect(image, "haarcascade_frontalface_default.xml",faces);
for (int i = 0; i < width; i++)
{
for (int j = 0; j < high; j++)
{
Bgr pixel = image[j,i];
System.Drawing.Point p = new System.Drawing.Point(j,i);
if (faces[0].Contains(p) && i<1540 && j<1980)
{
img.SetPixel(i, j, System.Drawing.Color.FromArgb(255, (int)pixel.Blue, (int)pixel.Green,(int) pixel.Red));
}
}
}
So can someone please point out where I'm going wrong?
Thank you very much.
EDITS : I've tried putting flags like faces[0]!=null which should take care of whether FaceDetection.Detect is actually returning anything but still I'm getting the same result.
I've also tried saving the ColorBitmap and testing it against the EMGU CV sample and it detects the faces in the image easily.
EDIT 2: So I've cross checked the co-ordinates of the rectangle which is being printed with the co-ordinates of the face being detected and the values of the Rectangle() being populated. They turn out to be almost same as far as I can see. So no luck there.
I don't know what else I can try for debugging.
If someone could point that out that would be great.
Thanks!
Ok I got it to work finally.
The problem was the Point[j,i] which should have been Point[i,j] . Also my FaceDetection method proved to be a little erratic and I had to fix that too to finally properly debug my code.
Related
I want to change the offset (2) of terrain texture through code.
I have added a road image as a texture on the terrain.
I've found related code online, but I am unable to figure out the role of renderer in this case.
More than code, I just want to know the first step that should be taken in order to change texture through code. (Settings basically).
And please mention the role of renderer.
In Unity Terrains textures are handled by the SplatPrototype class. See documentation
A Splat prototype is just a texture that is used by the TerrainData.
So if you want to change the Terrain's Texture you have to create a new SplatPrototype and set it to the splatPrototype variable of TerrainData.
There you can set the values of metallic, normalMap, smoothness, texture, tileSize and tileOffset of your choice.
You can use the following method:
private void SetTerrainSplatMap(Terrain terrain, Texture2D[] textures)
{
var terrainData = terrain.terrainData;
// The Splat map (Textures)
SplatPrototype[] splatPrototype = new SplatPrototype[terrainData.splatPrototypes.Length];
for (int i = 0; i < terrainData.splatPrototypes.Length; i++)
{
splatPrototype[i] = new SplatPrototype();
splatPrototype[i].texture = textures[i]; //Sets the texture
splatPrototype[i].tileSize = new Vector2(terrainData.splatPrototypes[i].tileSize.x, terrainData.splatPrototypes[i].tileSize.y); //Sets the size of the texture
splatPrototype[i].tileOffset = new Vector2(terrainData.splatPrototypes[i].tileOffset.x, terrainData.splatPrototypes[i].tileOffset.y); //Sets the size of the texture
}
terrainData.splatPrototypes = splatPrototype;
}
THIS WOKED FOR ME
splat[i].tileOffset = new Vector2(tar.splatPrototypes[i].tileOffset.x, tar.splatPrototypes[i].tileOffset.y+5f);
Splat Prototypes is Deprecated. I used TerrainLayers instead to edit the tiling size of the texture.
float[,,] splatMapData = terrain.terrainData.GetAlphamaps(0, 0, 100, 100);
for (int i = 26; i < 100; i++)
{
for (int j=0; j < 100; j++)
{
splatMapData[i, j, 0] = 0;
splatMapData[i, j, 1] = 0;
splatMapData[i, j, 2] = 1;
}
}
TerrainLayer[] layers = terrain.terrainData.terrainLayers;
layers[2].tileSize = new Vector2(100, 100);
terrain.terrainData.SetAlphamaps(0, 0, splatMapData);
terrain.Flush();
I need to perform some mathematical operations in photographs, and for that I need the floating point grayscale version of an image (which might come from JPG, PNG or BMP files with various colordepths).
I used to do that in Python using PIL and scipy.ndimage, and it was very straightforward to convert to grayscale with PIL and then to an array of floating-point numbers with numpy, but now I need to do something similar in C#, and I'm confused how to do so.
I have read this very nice tutorial, that seems to be a recurring reference, but that only covers the "convert to grayscale" part, I am not sure how to get an array of doubles from a Bitmap, and then (at some moment) to convert it back to System.Drawing.Bitmap for viewing.
I'm sure there are loads of optimal ways to do this.
As #Groo points out perfectly in the comments section, one could use for instance the LockBits method to write and read pixel colors to and from a Bitmap instance.
Going even further, one could use the graphics card of the computer to do the actual computations.
Furthermore, the method Color ToGrayscaleColor(Color color) which turns a color into its
grayscale version is not optically correct. There is a set of ratios which actually need to be applied to the color component strengths. I just used 1, 1, 1 ratios. That's accceptable for me and probably horrible for an artist or a scientist.
In the comments section, #plinth was very nice to point out to this question you should look at, if you want to make an anatomically correct conversion: Converting RGB to grayscale/intensity
Just wanted to share this really easy to understand and implement solution:
First a little helper to turn a Color into it's grayscale version:
public static Color ToGrayscaleColor(Color color) {
var level = (byte)((color.R + color.G + color.B) / 3);
var result = Color.FromArgb(level, level, level);
return result;
}
Then for the color bitmap to grayscale bitmap conversion:
public static Bitmap ToGrayscale(Bitmap bitmap) {
var result = new Bitmap(bitmap.Width, bitmap.Height);
for (int x = 0; x < bitmap.Width; x++)
for (int y = 0; y < bitmap.Height; y++) {
var grayColor = ToGrayscaleColor(bitmap.GetPixel(x, y));
result.SetPixel(x, y, grayColor);
}
return result;
}
The doubles part is quite easy. The Bitmap object is a memory representation of the actual image which you can use in various operations. The colordepth and image format details are only the concern of loading and saving instances of Bitmap onto streams or files. We needn't care about those at this point:
public static double[,] FromGrayscaleToDoubles(Bitmap bitmap) {
var result = new double[bitmap.Width, bitmap.Height];
for (int x = 0; x < bitmap.Width; x++)
for (int y = 0; y < bitmap.Height; y++)
result[x, y] = (double)bitmap.GetPixel(x, y).R / 255;
return result;
}
And turning a double array back into a grayscale image:
public static Bitmap FromDoublesToGrayscal(double[,] doubles) {
var result = new Bitmap(doubles.GetLength(0), doubles.GetLength(1));
for (int x = 0; x < result.Width; x++)
for (int y = 0; y < result.Height; y++) {
int level = (int)Math.Round(doubles[x, y] * 255);
if (level > 255) level = 255; // just to be sure
if (level < 0) level = 0; // just to be sure
result.SetPixel(x, y, Color.FromArgb(level, level, level));
}
return result;
}
The following lines:
if (level > 255) level = 255; // just to be sure
level < 0) level = 0; // just to be sure
are really there in case you operate on the doubles and you want to allow room for little mistakes.
The final code, based mostly in tips taken from the comments, specifically the LockBits part (blog post here) and the perceptual balancing between R, G and B values (not paramount here, but something to know about):
private double[,] TransformaImagemEmArray(System.Drawing.Bitmap imagem) {
// Transforma a imagem de entrada em um array de doubles
// com os valores grayscale da imagem
BitmapData bitmap_data = imagem.LockBits(new System.Drawing.Rectangle(0,0,_foto_franjas_original.Width,_foto_franjas_original.Height),
ImageLockMode.ReadOnly, _foto_franjas_original.PixelFormat);
int pixelsize = System.Drawing.Image.GetPixelFormatSize(bitmap_data.PixelFormat)/8;
IntPtr pointer = bitmap_data.Scan0;
int nbytes = bitmap_data.Height * bitmap_data.Stride;
byte[] imagebytes = new byte[nbytes];
System.Runtime.InteropServices.Marshal.Copy(pointer, imagebytes, 0, nbytes);
double red;
double green;
double blue;
double gray;
var _grayscale_array = new Double[bitmap_data.Height, bitmap_data.Width];
if (pixelsize >= 3 ) {
for (int I = 0; I < bitmap_data.Height; I++) {
for (int J = 0; J < bitmap_data.Width; J++ ) {
int position = (I * bitmap_data.Stride) + (J * pixelsize);
blue = imagebytes[position];
green = imagebytes[position + 1];
red = imagebytes[position + 2];
gray = 0.299 * red + 0.587 * green + 0.114 * blue;
_grayscale_array[I,J] = gray;
}
}
}
_foto_franjas_original.UnlockBits(bitmap_data);
return _grayscale_array;
}
I'm trying to use AForge in Unity and I have trouble converting the input data.
I have a 2-dimensional array storing pixel values that I need to convert to UnmanagedImage. I came up with the following code, but I am not sure if its the most efficient way:
img = UnmanagedImage.Create(sizx,sizy, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
for (int i =0;i<sizx;i++)
for (int j =0;j<sizy;j++){
int index = i+j*sizx;
img.SetPixel(i,j, new AForge.Imaging.RGB(t[index].r, t[index].g, t[index].b).Color);
}
Any help appreciated!
I've ended up using unsafe code and accessing the UnmanagedImage.ImageData directly:
unsafe
{
byte* dst = (byte*)data.Scan0.ToPointer();
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++, src++, dst += pixelSize)
{
dst[RGB.A] = input[src].A;
dst[RGB.R] = input[src].R;
dst[RGB.G] = input[src].G;
dst[RGB.B] = input[src].B;
}
dst += offset;
}
}
As it cannot be done in Unity, I had to modify the AForge library.
If you have your image represented as a byte[] (where each value represents a pixel color value from 0 to 255), then you can use UnmanagedImage.FromByteArray to create an UnmanagedImage from those values.
This method should work on Unity.
I need to load GIF animations and convert them frame by frame to bitmaps. To do that, I am extracting my GIF file frame by frame using Drawing.Imaging library and then casting each frame to bitmap.
Everything works just fine except the times when the consecutive frames are the same, when there is no pixel difference. The library seems to be dropping such frames.
I came to that conslusion with a simple test. I have created an animation of a circle that is growing and shrinking with a pause between the moment the last circle dissapears and the new one is not yet shown. When I play the animation consisting of my extracted bitmaps that pause is not present. If I compare the GIFs of the same frame-length but different amounts of identical frames, the returned totalframescount value is different. I have also observed that webbrowsers display identical consecutive frames correctly.
public void DrawGif(Image img)
{
FrameDimension dimension = new FrameDimension(img.FrameDimensionsList[0]);
int frameCountTotal = img.GetFrameCount(dimension);
for (int framecount = 0; framecount < frameCountTotal; framecount++)
{
img.SelectActiveFrame(dimension, framecount);
Bitmap bmp = new Bitmap(img); //cast Image type to Bitmap
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
Color color = bmp.GetPixel(i, j);
DrawPixel(i, j, 0, color.R, color.G, color.B);
}
}
Does someone encountered such a problem?
As I am pretty new to C# - is there a way to modify .NET lib ?
Maybe there is a solution to my problem that I am not aware of, that does not involve changing the library?
Updated code - the result is the same
public void DrawGif(img)
{
int frameCountTotal = img.GetFrameCount(FrameDimension.Time);
for (int framecount = 0; framecount < frameCountTotal; framecount++)
{
img.SelectActiveFrame(FrameDimension.Time, framecount);
Bitmap bmp = new Bitmap(img);
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
Color color = bmp.GetPixel(i, j);
DrawPixel(i, j, 0, color.R, color.G, color.B);
}
The Image is not saving duplicate frames, so you have to take the time of each frame into account. Here is some sample code based on this book in Windows Programming on how to get all the frames and the correct duration. An example:
public class Gif
{
public static List<Frame> LoadAnimatedGif(string path)
{
//If path is not found, we should throw an IO exception
if (!File.Exists(path))
throw new IOException("File does not exist");
//Load the image
var img = Image.FromFile(path);
//Count the frames
var frameCount = img.GetFrameCount(FrameDimension.Time);
//If the image is not an animated gif, we should throw an
//argument exception
if (frameCount <= 1)
throw new ArgumentException("Image is not animated");
//List that will hold all the frames
var frames = new List<Frame>();
//Get the times stored in the gif
//PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h
//More info on http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
var times = img.GetPropertyItem(0x5100).Value;
//Convert the 4bit duration chunk into an int
for (int i = 0; i < frameCount; i++)
{
//convert 4 bit value to integer
var duration = BitConverter.ToInt32(times, 4*i);
//Add a new frame to our list of frames
frames.Add(
new Frame()
{
Image = new Bitmap(img),
Duration = duration
});
//Set the write frame before we save it
img.SelectActiveFrame(FrameDimension.Time, i);
}
//Dispose the image when we're done
img.Dispose();
return frames;
}
}
We need a structure to save the Bitmap and duration for each Frame
//Class to store each frame
public class Frame
{
public Bitmap Image { get; set; }
public int Duration { get; set;}
}
The code will load a Bitmap, check whether it is a multi-frame animated GIF. It then loops though all the frames to construct a list of separate Frame objects that hold the bitmap and duration of each frame. Simple use:
var frameList = Gif.LoadAnimatedGif ("a.gif");
var i = 0;
foreach(var frame in frameList)
frame.Image.Save ("frame_" + i++ + ".png");
I'm using Webdriver with C#, the issue is that Webdriver can't test design, so i trying to make something like screenshot comparison, because i working on big site and every day it has new futures, new changes so i don't know where or on which browser design didn't broke. My question is do you know any tool, framework, project or some ideas?
I already wrote something but its not so perfect, my code makes screenshots over site on different browsers and versions, after that it's cutting them and compare it with demo-screen. If there are more than 5% for wrong pixels test is falling.
P.S. I'm a junior)
Some of my code if someone will need it in the future:
var screenshot = ((ITakesScreenshot)Global.Driver).GetScreenshot();
screenshot.SaveAsFile(dirHomePage + "homepage.png", ImageFormat.Png);
var mainImg = new Bitmap(File.OpenRead(dirHomePage + "homepage.png"));
var section = new Rectangle(new Point(0, 0), new Size(mainImg.Width, 153));
this.header = this.CropImage(mainImg, section);
this.header = this.ClearImage(this.header, Color.White, 264, mainImg.Width, 30, 60);
ImageComparison(this.header, this.demoHeader);
public Bitmap ClearImage(Bitmap source, Color color, int fromW, int toW, int fromH, int toH)
{
Bitmap bmp = source;
for (int i = fromW; i < toW; i++)
{
for (int j = fromH; j < toH; j++)
{
bmp.SetPixel(i, j, color);
}
}
return bmp;
}
public Bitmap CropImage(Bitmap source, Rectangle section)
{
Bitmap bmp = new Bitmap(section.Width, section.Height);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(source, 0, 0, section, GraphicsUnit.Pixel);
return bmp;
}
public void ImageComparison(Bitmap firstImg, Bitmap secondImg)
{
bool match = false;
int nrBadPixels = 0;
if (firstImg.Width.Equals(secondImg.Width) && firstImg.Height.Equals(secondImg.Height))
{
double acceptedProcent = (firstImg.Width * firstImg.Height) * 0.05;
for (int i = 0; i < firstImg.Width; i++)
{
for (int j = 0; j < firstImg.Height; j++)
{
string firstImgRef = firstImg.GetPixel(i, j).ToString();
string secondImgRef = secondImg.GetPixel(i, j).ToString();
if (firstImgRef != secondImgRef)
{
nrBadPixels++;
if (nrBadPixels > acceptedProcent)
{
match = false;
break;
}
match = true;
}
}
}
}
Assert.IsTrue(match);
}
I think you can give Sikuli a try.
Sikuli Script automates anything you see on the screen. It uses image
recognition to identify and control GUI components. It is useful when
there is no easy access to a GUI's internal or source code.
However, this is just for layout and stuff, if you need to test functionality based on DOM, Selenium WebDriver is still the best way to go. Moreover, it's more like Selenium IDE, rather than Selenium WebDriver C#. You might find this wiki page interesting, SikuliWebDriver.
I have wrote a small code snippet that solve Your problem. It scrolls to the element plus width and height and then cutout only the area of the element.
Look at my Blog
https://modern-coding-today.blogspot.com/2018/11/c-net-make-partial-screenshots-in.html
public static Bitmap GetElementScreenshot(IWebElement element) {
IWebDriver driver = ((IWrapsDriver)element).WrappedDriver;
Actions actions = new Actions(driver);
actions.MoveToElement(element);
actions.Perform();
IJavaScriptExecutor executor = (IJavaScriptExecutor)driver;
int yOffset = Convert.ToInt32(executor.ExecuteScript($"window.scrollBy({element.Size.Width}, {element.Size.Height}); return window.pageYOffset;"));
Screenshot sc = ((ITakesScreenshot)driver).GetScreenshot();
var img = Image.FromStream(new MemoryStream(sc.AsByteArray)) as Bitmap;
return img.Clone(new Rectangle(element.Location.X, element.Location.Y - yOffset, element.Size.Width, element.Size.Height), img.PixelFormat);
}
In my Blog You will find this code as a IWebDriver Extension also.