Graphics performance optimization issue - wpf

Here's the problem :
I need to scroll a huge image of a wave form that has been rendered previously,
WPF didn't let me assign that huge (80000*256) picture to an Image,
it works for smaller (30000*256) images but it's so slow animating it that it's unpractical.
So what I decided was to use a WriteableBitmap that I assign to my Image.Source,
and then I only have to update say 1920*256 (or only the width of the screen).
It works much better now but after some profiling, it seems that
the actual copying process takes quite some time and it's not 60 fps everytime.
I am already writing to the bitmap by locking it and using pointers.
My question is :
Do you know any (faster) way to update a bitmap ?
These pixels are already in memory in the huge bitmap, reading straight from here seems a wise idea; well, get rid of the WriteableBitmap between my Image.Source and my BitmapData.
Thanks for your help :)

You can try using BitmapSource.CopyPixels to extract the bytes with color information from the image (not sure if you need that) and BitmapSource.Create that creates a bitmap from a byte array (or its overload which can grab color information directly from unmanaged memory).

You can try using InteropBitmap to update the pixels as WriteableBitmap is kind of slow with its CPU bound internal operations. I have some code here that uses it: http://silverlightviewport.codeplex.com/SourceControl/changeset/view/57274#1534506
It's hardcoded for Bgra32, which is the only color space supported by InteropBitmap in 3.5 SP1. In 4.0 it should support 24 bit color spaces.

I have fixed it, using GC.Collect; still can't believe it fixed the problem.
Don't know if it's a good practice but it works ...
That gave me headaches and nightmares the last few days but now most is sorted.
The funny conclusion I'll have about this, is that GCCollectionMode.Optimized,
thinks it's never the time to collect memory, it went up to use 2Gb,
destabilizing the whole system (Windows) up to the point it freezes the mouse, lol ...
Thanks for your help :-)

Related

Image processing..back ground subtraction

I have a sequence of images taken from a camera. The images consists of hand and surroundings. I need to remove everything except the hand.
I am new to Image processing. Would anyone help me in regard with the above Question. I am comfortable using C and Matlab.
A really simple approach if you have a stationary background and a moving hand (and quite a few images!) is simply to take the average of the set of images away from each image. If nothing else, it's a gentle introduction to Matlab.
The name of the problem you are trying to solve is "Image Segmentation". The Wikipedia page here: wiki is a good start.
If lighting consistency isn't a problem for you, I'd suggest starting with simple RGB thresholding and see how far that gets you before trying anything more complicated.
Have a look at OpenCV, a FOSS library for computer vision applications. Specifically, see the Video Surveillance module. For a walk through of background subtraction in MATLAB, see this EETimes article.
Can you specify what kind of images you have. Is the background moving or static? For a static background it is a bit straightforward. You simply need to subtract the incoming image from the background image. You can use some morphological operations to make it look better. They all depend on the quality of images that you have. If you have moving background I would suggest you go for color based segmentation. Convert the image to YCbCr then threshold appropriately. I know there are some papers available on it(However I dont have time to locate them). I suggest reading them first. Here is one link which might help you. Read the skin segmentation part.
http://www.stanford.edu/class/ee368/Project_03/Project/reports/ee368group08.pdf
background subtraction is simple to implement (estimate background as average of all frames, then subtract each frame from background and threshold resulting absolute difference) but unfortunately only works well if 1. camera has manual gain and exposure 2. lighting conditions do not change 3.background is stationary. 4. the background is visible for much longer than the foreground.
given your description i assume these are not the case - so what you can use - as already pointed out - is colour as a means of segmenting foreground from background. as it's a hand you are trying to isolate best bet is to learn the hand colour. opencv provides some means of doing this. if you want to do this yourself you just get the colour of some of the hand pixels (you would need to specify this manually for at least one frame) and convert them to HUE (which encapsulates the colour in a brightness independen way. skin colour has a very constant hue) and then make a HUE histogram. compare this to the rest of the pixels and then decided if the hue is simmilar enough.

WPF tabswitch/ render takes too much time

I have a WPF application with many tabs..
in one tab.. i make a verycomplex vector drawing consisting of thousands of drawing visuals.. (this represents a machine and all elements need to be interactable..)
It takes 3/4 seconds for drawing this for the first time..After the first draw it should be done..
The problem is if i switch to another tab and comeback, it takes atlease 2,3 seconds to show the tabpage with drawing again.. Since there is no redraw, why should it take so much time..?
If the component is not going to change, you could call Freeze() on it to mark it as done. Without trying it out I don't know if that would help, but you could give it a shot.
Not all objects are Freezable. Check out the MSDN documentation for more info:
http://msdn.microsoft.com/en-us/library/ms750509.aspx
Another thing you could try would be rendering the vector art to a bitmap, and displaying that. Maybe it makes you feel icky to lose the vector precision, but if you know it's not going to change and it will look the same, what's the harm? (If you support printing or something that will require a hi-res version, you could always switch back for that operation.) For info on how to convert a UIElement to a bitmap, check out:
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.rendertargetbitmap.aspx
Another possible solution: You don't really explain what kind of interaction you are doing with the elements, but if all you want to do is zoom and pan, a RenderTransform may be good enough (which is more efficient than a LayoutTransform and/or moving all the elements individually). I haven't played around with combining Freeze() and a RenderTransform, but you may be able to get the desired zooming while reducing the amount of layout WPF has to do.

WPF - Is RenderTargetBitmap better than changing an Image Source?

Im trying to create a PNG sequencer class that will allow me to change an ImageBrush's ImageSource property via an animation.
The issue is that I have around 150 PNG files to load, and it really really affects performance when I have a few animations on the screen.
I have read a little about RenderTargetBitmap and also WriteableBitmap but Im not sure how to get a big performance boost, because I really do need it.
Im getting down to 6fps in some cases, which is obviously not acceptable.
In my Sequencer class, I just update a CurrentFrame DP that changes the ImageSource property of the ImageBrush.
Any ideas on how to increase the performance here?
Step 1 is loading all your images in ahead of time (preferably on a background thread). You should have your BitmapImage objects initialized with the CacheOption = BitmapCacheOption.OnLoad. You may already be doing this or it might not be the problem (the images cache by default).
However the rendering thread also needs to do some work when you change the image source. If you're not displaying at the source image size, that might be a problem, as by default the Image control uses the high quality Fant scaling algorithm. In that case you could get a performance increase by calling RenderOptions.SetBitmapScalingMode(uiImage, BitmapScalingMode.LowQuality); on your Image. Low quality scaling is orders of magnitude faster. However even after that there's still a bit of work involved. If you want to get the fastest animation possible, you can create an Image control for every frame, then overlap them all on the same place and change which one appears on top. You'll still take the hit on the render thread loading all the images in, but the actual animation should be quite snappy.

WPF 3D video memory efficiency

Ill try to explain my situation as best as I can, sorry if it is not too clear...
I have a Viewport3D that contains some large 3d rectangles that are like big crystals.
When the user click on one of the crystals, I add a new material to the crystal in the spot the use clicked using an ImageBrush. I then iterate over a list of bitmaps (List<BitmapImage> collection) and update the ImageBrush each frame to create an animation on the 3D crystal.
This works nice and I have up to 5 different effects playing on the crystals, but after profiling my application, I have discovered that due to mipmaps (I think) and the way 3d renders, my video memory jumps through the roof!!
By my calculation, if I have a 75 frame animation, by 400x400 running at 4 bytes per pixel, and having ~5 different animations piled up, you can see how this can get large :)
75 * 400 * 400 * 4 * 5 = ~250MB
this is an issue, not only because of the size, but also, the BitmapImages stay in Video Memory until I make them null, which is very annoying and performance costly.
My idea to fix this is to change from having List<BitmapImage> collection, to having a List<Byte[]> and rather than updating an ImageSource, I would like to try to use a WriteableBitmap that write the bytes to it.
The issue is I have no idea how to read bytes from a PNG file, then create a WriteableBitmap and write the bytes to it over and over in an efficient manor.
Can anyone please help me out?
WriteableBitmap is actually pretty bad with performance, even though it takes dirty regions. Try using the InteropBitmap. I have an class ready to go for it here:
http://silverlightviewport.codeplex.com/SourceControl/changeset/view/33100#809062

WPF render performance with BitmapSource

I've created a WPF control (inheriting from FrameworkElement) that displays a tiled graphic that can be panned. Each tile is 256x256 pixels at 24bpp. I've overridden OnRender. There, I load any new tiles (as BitmapFrame), then draw all visible tiles using drawingContext.DrawImage.
Now, whenever there are more than a handful new tiles per render cycle, the framerate drops from 60fps to zero for about a second. This is not caused by loading the images (which takes in the order of milliseconds), nor by DrawImage (which takes no time at all, as it merely fills some intermediate render data structure).
My guess is that the render thread itself chokes whenever it gets a large number (~20) of new BitmapSource instances (that is, ones it had not already cached). Either it spends a lot of time converting them to some internal DirectX-compatible format or it might be a caching issue. It cannot be running out of video RAM; Perforator shows peaks at below 60MB, I have 256MB. Also, Perforator says all render targets are hardware-accelerated, so that can't be it, either.
Any insights would be appreciated!
Thanks in advance
Daniel
#RandomEngy:
BitmapScalingMode.LowQuality reduced the problem a little, but did not get rid of it. I am already loading tiles at the intended resolution. And it can't be the graphics driver, which is up-to-date (Nvidia).
I'm a little surprised to learn that scaling takes that much time. The way I understood it, a bitmap (regardless of its size) is just loaded as a Direct3D texture and then hardware-scaled. As a matter of fact, once the bitmap has been rendered for the first time, I can change its rotation and scale without any further freezes.
It's not just with a large number of images. Just one large image is enough to hold up rendering until it has been loaded in, and that can be quite noticable when your image dimensions start getting up in the thousands.
I do agree with you that it's probably the render thread: I did a test and the UI thread was still happily dispatching messages while this render delay was taking place from trying to display a fully pre-cached BitmapImage.
It must be doing some sort of conversion or preparation on the image, like you were speculating. I've tried to mitigate this in my app by "rendering" but hiding the image, then revealing it when I need to show it. However this is less than ideal because the rendering freezes happen anyway.
(Edit)
Some followup: After a discussion on the MS WPF alias I found what was causing the delays. On my Server 2008 machine it was a combination of old video drivers that don't support the new WDDM driver model and a delay for resizing the image.
If the source image size is different from the display size, that will delay the render thread before the image shows up. By default an image is set to the highest quality, but you can change the scaling options for rendering by calling RenderOptions.SetBitmapScalingMode(uiImage, BitmapScalingMode.LowQuality); . Once I did that, the mysterious freeze before displaying an image went away. An alternative, if you don't like the quality drop in scaling, is to load the BitmapImage with DecodePixelWidth/Height equal to the size it will be displayed at. Then if you load the BitmapImage on a background thread, you should have no delay in displaying it.
Also try these;
/* ivis is declared in XAML <Image x:Name="iVis" UseLayoutRounding="True" SnapsToDevicePixels="True" /> */
iVis.Stretch = Stretch.None;
RenderOptions.SetBitmapScalingMode(iVis, BitmapScalingMode.NearestNeighbor);
RenderOptions.SetEdgeMode(iVis, EdgeMode.Aliased);
VisualBitmapScalingMode = BitmapScalingMode.NearestNeighbor;
iVis.Source = **** your bitmap source ****
I was having some trouble with performance when using a huge amount of "A" channel color's, waiting until after the image had rendered to scale it worked much better for me.
Also, as you said your using a tiled graphic?
You would usually use a TileBrush to simply set as the Brush on your FrameworkElement. If you are animating them or adding new ones dynamically, you could generate your brushes then apply them to your object as you go manually too, be sure to Freeze them if you can. Also, VisualBitmapScalingMode is a property of any Visual.

Resources