I would like to generate a grid picture or bitmap or anything similar with raw pixel data in swift. Since the pixel location, image size etc. are not determined before the user opens the app or presses a refresh button I need a fast way to generate 2732x2048 or more individual pixels and display them on the screen.
First I did use UIGraphicsBeginImageContextWithOptions and drew each pixel with a 1x1 CGRect but this obviously did not scale well.
Afterwards I have used this approach: Pixel Array to UIImage in Swift
But this is still kind of slow with the bigger screens.
Could something like this be done with MetalKit? I would assume that a lower api does render something like this way faster?
Or is there any better way to process something like this in-between MetalKit and CoreGraphics?
Some info regarding the structure of my data:
There is a struct with the pixel color data red, green, blue, alpha for each individual pixel stored as an Array and two image size variables: imageHeight and imageWidth.
The most performant way to do that is to use Metal Compute Function.
Apple has a good documentation to illustrate GPU programming.
Performing Calculations on a GPU
Processing a Texture in a Compute Function
Related
I'm making a simple camera app for iOS and MAC. After the user snaps a picture it generates a UIimage on iOS (NSImage on MAC). I want to be able to highlight the areas in the image that is over exposed. Basically the overexposed areas would blink when that image is displayed.
Anybody knows the algorithm on how to tell where on the image is overexposed. Do I just add up the R,G,B values at each pixel. And if the total at each pixel is greater than a certain amount, then start blinking that pixel, and do that for all pixels?
Or do I have to do some complicated math from outer space to figure it out?
Thanks
rough
you will have to traverse the image, depending on your desired accuracy and precision, you can combine skipping and averaging pixels to come up with a smooth region...
it will depend on the details of you color space, but imagine YUV space (because you only need to look at one value, the Y or luminance):
if 240/255 is considered white, then a greater value of say 250/255 would be over exposed and you could mark it, then display in an overlay.
I am using GPUImage to process incoming video and I would like to then consider a given square subregion of the image and determine the average pixel value of the pixels in that region. Can anyone advise me on how to accomplish this? Even information on how to acquire pixel data for a pixel at coordinate(x,y) in the image would be useful.
Apologies if this is a simple question, but I am new to computer vision and the way to do this was not clear to me from the available documentation. Thank you.
First, use a GPUImageCropFilter to extract the rectangular region of your original image. This uses normalized coordinates (0.0 - 1.0), so you'll have to translate from the pixel location and size to these normalized coordinates.
Next, feed the output from the crop filter into a GPUImageAverageColor operation. This will average the pixel color within that region and use the colorAverageProcessingFinishedBlock that you set as a callback. The block will return to you the average red, green, blue, and alpha channel values for the pixels in that region.
For an example of both of these operations in action, see the FilterShowcase example that comes with the framework.
I am trying to develop an OCR in VB6 and I have some problems with BMP format. I have been investigating the OCR process and the first step is to convert the image in "black and white" with a threshold. The conversion process is easy to understand and I have done it. However, I'm trying to reduce the size of the resulting image because it uses less colors (each pixel only has 256 possible values in grayscale). In the original image I have 3 colors (red, green and blue) but now I only need one color (the value in grayscale). In this moment I have achieved the conversion but the resulting grayscale images have the same size as the original color image (I assign the same color value in the three channels).
I have tried to modify the header of the BMP file but I haven't achieved anything and now I don't understand how it works. For example, if I convert the image with paint, the offset that is specified in the header changes its value. If the header is constant, why does the offset change its value?.
The thing is that a grey-scale bitmap image is the same size as a color bitmap image because the data that is used to save the grey colors takes just as much space as the color.
The only difference is that grey is just 3 times that same value. (160,160,160) for example with color giving something like (123,200,60). The grey values are just a small subset of the RGB field.
You can trim down the size after converting to grey-scale by converting it from 24 bit to 16 bit or 8-bit for example. Although it depends on what you are using to do the conversion whether that is already supplied to you. Otherwise you'll have to make it yourself.
You can also try using something else than BMP images. PNG files are lossless too, and would even save space with the 24 bit version. Image processing libraries usally give you several options as output formats. Otherwise you can probably find a library that does this for you.
You can write your own conversion in a "lockbits" method. It takes a while to understand how to lock/unlock bits correctly, but the effort is worth it, and once you have the code working you'll see how it can be applied to other scenarios. For example, using an lock/unlock bits technique you can access the pixel values from a bitmap, copy those pixel values into an array, manipulate the array, and then copy the modified array back into a bitmap. That's much faster than calling GetPixel() and SetPixel(). That's still not the fastest image manipulation code one can write, but it's relatively easy to implement and maintain the code.
It's been a while since I've written VB6 code, but Bob Powell's often has good examples, and he has a page about lock bits:
https://web.archive.org/web/20121203144033/http://www.bobpowell.net/lockingbits.htm
In a pinch you could create a new Bitmap of the appropriate format and call SetPixel() for every pixel:
Every pixel (x,y) in your 24-bit color image will have a color value (r,g,b)
After conversion to a 24-bit gray image, each pixel (x,y) will have a three equal values for each color channel; that can be expressed as (n,n,n) as Willem wrote in his reply. If all three colors R,G,B have the same value, then you can say that color value is the "grayscale" value of that pixel. This is the same shade of gray that you will see in your final 8-bit bitmap.
Call SetPixel for each pixel (x,y) in a newly created 8-bit bitmap that is the same width and height as the original color image.
I'll get straight to the point :)
From the above 480 x 320 diagram, I am thinking I can detect collision on pixel level like a worm game.
What I want to know is how to sample pixels on separate layers. As you can see in the diagram, as the worm is falling, I want to only sample the black pixels with glReadPixels() to see if the worm is standing (colliding) with any terrain but when I last tried it, glReadPixels() samples all pixels on screen, without any ideas of "layers".
The white pixel is the background that should not be part of the sampling.
Am I perhaps suppose to have a black and white copy of my terrain on a separate buffer and call glReadPixels() on that separate buffer so that the background images (white pixels) won't get sampled?
Before I was drawing my terrain on the screen in the same buffer/context where I draw my background image.
Any ideas?
What read pixels does is read back the binded buffer, since the buffer is the output of all your compositions, will obviously contain all the data your wrote and doesn't understand you logic arrangement into layer. You can try drawing your terrain into the stencil buffer and read back only that. Use GL_DEPTH_STENCIL (format parameter).
Assume the image is only in black and white.
Is there a software that can generate a matrix representation for the text on the image?
You should take a look at OCR-Software.
If you're referring to an image like the one below, then it's pretty straight forward.
You just do the following:
Read the image into a 2D byte array so you can access the pixels
Loop through the array and look for every black pixel (0)
Store these in a matrix however you need to
This assumes that lettering is pure black on white, you might have to allow values upto a certain value (5 or 10) if this isn't the case.