Convert image to array of floats and back in .NET - c#

I have code in Python that opens an image as grayscale, converts it to a numpy float array, perform a lot of mathematical operations on it, then normalizes and converts it to binary image (1 bit per pixel), saving it to disk again (PNG file).
Which .NET classes (preferrably) should I use to perform similar operations?
Below is a subset of my Python code:
im = Image.open(in_name)
a = numpy.asarray(im.convert('L'), dtype=float) ## implicit conversion to grayscale
## lots of element-wise arithmetical operations with 'a'
## and other similar-shaped arrays from other images
out_im = Image.fromarray(a.astype('uint8')).convert('1')
out_im.save(out_name)

There are 2 ways to do this. You'll need XNA or DirectX in order to do either.
In XNA Texture2D objects contains the GetData and SetData methods which do what you want.
You can also use HLSL pixel shaders on a Texture2D to manipulate it. You can change your rendering target to render to another Texture2D which you save as an image file.
The second would be the fastest and most efficient, the first would be the easiest.

Related

Fast way to convert large vectorial images to binary matrix

I have complex vectorial images I need to convert to binary matrix (a kind of rasterizing) with high precision, using necessarily c#. Currently I'm doing it by painting vectorial images in a bitmap and reading the internal bitmap array. Then I convert this array in a binary matrix where 1 indicates that the corresponding pixel is of a specific color, and 0 when is not. As I access the internal bitmap array directly, that's fast and allows using Parallel.For
The problem is that I need to obtain very high definition matrixes of the images (50000x25000 or more). Therefore I have to paint each vectorial image dividing it in several parts, as a bitmap of this size is not supported.
As I have a lot of images to convert, it is very slow.
I'm looking for a fast way of doing that without loosing precision (ideally even increasing it). And I need to integrate this feature in a c# application.
I finally used Gdal rasterize tool, passing polygons as shapefiles, and it works quite well and fast.

In Unity how do I convert a compressed Texture Asset to in-memory RGB24?

I'm trying to pass a static Texture2D asset to a library, but it expects RGB24, RGB32, or RGB32A only. Those are uncompressed, so storing my texture in that format isn't really an option, it'd be enormous.
If I have my Texture2D stored in a compressed format, how can I convert it to RGB24 (or RGB32) in memory?
I know how to create a new Texture with the right format and size, I just don't know how to move the image data without a shader and rendertarget and so on, but I assume there's a quicker and easier way.
So, in C#, how to convert a compressed Texture Asset to in-memory RGB24?
First mark your texture as read/write in the import settings. Then you can use Texture2D.GetPixels32 to retrieve pixel data. If your library doesn't support the default format unity provides with Color32 (it's either ARGB or RGBA, can't remember) you'll have to convert it manually.

Loss of brightness/contrast when converting from Image<Gray,float> to Image<Gray,Byte>

We are using OpenCV with Emgu 2.4.9 wrapper.
When we convert the Image<Gray,float> to Image<Gray,Byte> (using convert<Gray,Byte>()), the brightness/contrast is reduced.
We are using Image<Gray,Byte> for display purposes while Image<Gray,float> is used temporarily for processing (e.g. convolution).
However, when Image<Gray,float> is saved as JPEG, I see the required level of intensities/brightness.
When I checked the Image.Save() method, it looks like it finally ends up calling OpenCV imwrite_() function which in turn converts the Float image to byte format: ‘image.convertTo( temp, CV_8U );’
So, I would expect the intensity level to have reduced when Image<Gray,float> is saved to JPEG. But it does not (even though, the same convertTo() method, which in turn calls OpenCV cvt_() function).
But, when the float image converted to Byte and saved the brightness/contrast is reduced.
In both cases, I believe, saturate_cast<> would be called.
Related questions here: Emgu image conversion from Image<Gray,float> to Image<Gray,Byte> results in intensity loss?
Would someone be able to describe what is going on and how to preserve the brightness/intensity when converting from Image<Gray,float> to Image<Gray,Byte>?

Image won't replace while the program is running

I'm trying to make a screen sharing program, the program flows will be like this:
capture screen
slice to 9
compare new slice with old slice
replace the different slice
upload to web (with new slice)
But I've got some problems with replacing the slices (in replace function). From all the source I have searched I need to convert the bitmap image (the slice) to string, then I can replace. but there's no example for converting bitmap double array to strings.
Is there any possibility to replace the image without convert it to strings?
Why would you need to replace bitmap data using a string as intermediate? You can use bitmap manipulation functions just fine. Also, I'm having trouble understanding your algorithm. You get a bitmap of the whole screen. Then you cut it into 9 parts (are those the corners, edges and center?), compare each of the slices to their old versions one by one, replace the ones that changed, and then you upload the whole bitmap? Don't you want to upload each of the slices separately, only uploading the ones that changed? Otherwise it doesn't really make sense to do the slicing at all, or does it?
Now, it's true that converting the data to string lets you use the string comparison functions and other stuff like that, but that's an awful idea. The fastest way to compare two byte arrays would be using the memcmp function in msvcrt.dll. This answer gives you the solution to that - https://stackoverflow.com/a/2038515/3032289, including reading the data from the original bitmaps.
Then you just send the slices that aren't the same as their older versions and you're done, no replacing needed.
Probably the best way is to perform a Base64 encoding
Google for base64 C++ source code.

A function like "glReadPixels" in DirectX / SharpDX

I'm searching for a way to read a pixels color at the mousepoint. In OpenGL it was done by calling the function "glReadPixels" after drawing the scene (or parts of it). I want to make a simple color picking routine in the background, for identifing a shapes / lines in 3D Space.
So, is there any equivalent method/function/suggestion for doing the same in SharpDX (DirectX10 / DirectX11) ?
This is perfectly possible with Direct3D11: simply follow these steps:
Use DeviceContext.CopySubResourceRegion to copy part from the source texture to a staging texture (size of the pixel area you want to readback, same format, but with ResourceUsage.Staging)
Retrieve the pixel from this staging texture using Device.Map/UnMap.
There is plenty of discussion about this topic around the net (for example: "Reading one pixel from texture to CPU in DX11")
Another option is to use a small compute shader, like :
Texture2D<float4> TextureInput: register(t0);
StructuredBuffer<float2> UVBuffer: register(t1);
RWStructuredBuffer<float4> RWColorBuffer : register(u0);
SamplerState Sampler : register( s0 );
[numthreads(1, 1, 1)]
void CSGetPixels( uint3 DTid : SV_DispatchThreadID )
{
float4 c = TextureInput.SampleLevel(Sampler , UVBuffer[DTid.x].xy, 0);
RWColorBuffer [DTid.x] = c;
}
It gives you the advantage of being a bit more "format agnostic".
Process is then like that.
Create a small structured buffer for UV (float2) (pixel position/texture size, don't forget to flip Y axis of course). Copy the pixel position you want to sample into this buffer.
Create a writeable buffer and a staging buffer (float4). Needs to be same element count as your uv buffer.
Bind all and Dispatch
Copy writeable buffer into the staging one.
Map and read float4 data in cpu
Please note I omitted thread group optimization/checks in compute shader for simplicity.
Since you're using C#, my suggestion would be to use GDI+, as there is no such function like "glReadPixels" in DX. GDI+ offers very easy methods of reading the color of a pixel at your mouse pointer. Refer to stackoverflow.com/questions/1483928.
If GDI+ is a no go, as it isn't very fast, can't you stick to the usual object picking using a "Ray"? You want to identify (I suppose 3-dimensional) shapes/lines, this would be easy using a ray (and check for intersection) to pick them.

Categories

Resources