Track a person by his clothes color using the Kinect sensor - image-processing

I'm new to the image processing, and I'm working on a simple project to recognize people by their clothes color. I'm not sure what the best way is to do that. Since I'm using the Kinect (with Kinect-SDK), it is easy to detect people using the depth stream, and by mapping the depth data to the color data, I can get the color pixels of the people. I tried to build a color histogram for each person to recognize the person color. I'm not sure if this right or not!
What I'm doing is:
1- Get the depth data from the Kinect device.
2- Ensure if a pixel is a player pixel or not by using the Player Index.
3- Map player pixels to color pixels.
4- Build a color histogram for the player.
I have a problem dealing with step 4. This is how I'm trying to build the histogram (32 bins):
color = ColorPixelData[colorPixelIndex];
B_Values[color / 8]++;
color = ColorPixelData[colorPixelIndex + 1];
G_Values[color / 8]++;
color = ColorPixelData[colorPixelIndex + 2];
R_Values[color / 8]++;
I think I'm doing it in a wrong way. The colors values look very different every time I run the program on the same scene.
Could anyone give me some points?
Any help will be appreciated.

Color histogram wont help you. Back in the day when i was doing some face recognition tool, color histogram would give different values for the pictures that look almost alike. So it's not a way to go. Instead of building a color histogram you could see how much for example red color is present on the scene, if someone of your subjects is wearing a red jacket.

Related

Add a darkening filter to an image OpenCV

I apologize in advance if a question like this was already answered. All of my searches for adding filters resulted in how to add dog faces. I wasn't sure what the proper terminology is.
What techniques do phone apps (such as Snapchat's text overlay or a QR code program for android) use to "darken" a section of the image? I am looking to replace this functionality in OpenCV. Is it possible to do this with other colors? (Such as adding a blue accent)
Example: Snapchat text overlay
https://i.imgur.com/9NHfiBY.jpg
Another Example: Google Allo QR code search
https://i.imgur.com/JnMzvWT.jpg
Any questions or comments would be appreciated
In General:
Change of brightness can be achieved via Addition/Subtraction.
If you want to brighten your Image, you can add a specific amount (e.g. 20) to each channel of the image. The other way around for darkening (Subtraction).
If you would subtract 50 from each channel of the image, you would get:
To darken pixel dependent you could also use Division. This is how a division with 1.5 would change the image:
Another way would be to use the Exponential Operator. This operator takes the value of each channel and will then calculate pixel^value. The resulting value will be then scaled back to the 0-255 range (for 8 bit RGB) via looking the highest value and then calculating the scaling factor via 255/resulting value.
If use it with values > one, it will darker the image. This is because
Here a chart how the exponential operator will change the value of each pixel. As you can see, values for the operator above 1 will darken the image (meaning the channels will be shifted towards lower values), whilst values below 0 will shift all pixels towards white and thus increase brightness.
Here is an example image for application of the operator using the value 0.5, meaning you take each pixel^0.5 and scale it back to the range of 0-255:
For a value of 2 you get:
Sadly i can not help you further, because i am not familiar with OpenCV, but it should be easy enough to implement yourself.
For your question about tinting: Yes, that is also possible. Instead of shifting towards white, you would have to shift the values of each pixel towards the respective color. I recommend to inform you about blending.
Original image taken from here
Update: I was able to darken an image by blending an image matrix with a black matrix. After that, it was just a matter of darkening certain parts of the image to replicate an overlay.
The lower the alpha value is, the darker the image.
Result
void ApplyFilter(cv::Mat &inFrame, cv::Mat &outFrame, double alpha)
{
cv::Mat black = cv::Mat(inFrame.rows, inFrame.cols, inFrame.type(), 0.0);
double beta = (1.0 - alpha);
cv::addWeighted(inFrame, alpha, black, beta, 0.0, outFrame);
}
https://docs.opencv.org/2.4/doc/tutorials/core/adding_images/adding_images.html
Thank you for the help everyone!

GPUImage Histogram Equalization

I would like to use GPUImage's Histogram Equalization filter (link to .h) (link to .m) for a camera app. I'd like to use it in real time and present it as an option to be applied on the live camera feed. I understand this may be an expensive operation and cause some latency.
I'm confused about how this filter works. When selected in GPUImage's example project (Filter Showcase) the filter shows a very dark image that is biased toward red and blue which does not seem to be the way equalization should work.
Also what is the difference between the histogram types kGPUImageHistogramLuminance and kGPUImageHistogramRGB? Filter Showcase uses kGPUImageHistogramLuminance but the default in the init is kGPUImageHistogramRGB. If I switch Filter Showcase to kGPUImageHistogramRGB, I just get a black screen. My goal is an overall contrast optimization.
Does anyone have experience using this filter? Or are there current limitations with this filter that are documented somewhere?
Histogram equalization of RGB images is done using the Luminance as equalizing the RGB channels separately would render the colour information useless.
You basically convert RGB to a colour space that separates colour from intensity information. Then equalize the intensity image and finally reconvert it to RGB.
According to the documentation: http://oss.io/p/BradLarson/GPUImage
GPUImageHistogramFilter: This analyzes the incoming image and creates
an output histogram with the frequency at which each color value
occurs. The output of this filter is a 3-pixel-high, 256-pixel-wide
image with the center (vertical) pixels containing pixels that
correspond to the frequency at which various color values occurred.
Each color value occupies one of the 256 width positions, from 0 on
the left to 255 on the right. This histogram can be generated for
individual color channels (kGPUImageHistogramRed,
kGPUImageHistogramGreen, kGPUImageHistogramBlue), the luminance of the
image (kGPUImageHistogramLuminance), or for all three color channels
at once (kGPUImageHistogramRGB).
I'm not very familiar with the programming language used so I can't tell if the implementation is correct. But in the end, colours should not change too much. Pixels should just become brighter or darker.

Perlin noise, how to detect bright/dark areas?

I need some help with perlin noise.
I want to create a random terrain generator. I am using perlin noise in order to determine where the mountains and sea should go. From the random noise, I get something like this:
http://prntscr.com/df0rqp
Now, how can I actually detect where the brighter and darker areas are?
I tried using display.colorSample which returns the RGB color and alpha of the pixel, but this doesn't really help me much.
If it was only white and red, I could easily detect where the bright area is (white would be really big, where red would be small number) and the opposite.
However, since I have red, GREEN AND BLUE, this makes it a hard job.
To sum up, how can I detect where the white and where the red areas at?
You have a fundamental misunderstanding here. The perlin noise function really only goes from (x,y)->p . [It also works in higher dimensions]. But what you are seeing is just your library being nice. The noise function goes from two reals to one. It is being helpful by mapping the one result value p to a color gradient. But that is only for visualization. p is not a color, just another number. Use that one directly! If p<0 you might do water.
I would suggest this:
1. Shift hue of the image into red color like here
2. Use red channel to retrieve some mask.
3. Optional: scale max/min brightness into 0-255 range.

360 FOV depth buffer by topology and 2D shadows with multiple lights

Just implemented the idea with multiple lights (idea without multiple lights is here 360 FOV depth buffer by topology and 2D shadows), however i'm not sure if its correctly rendered http://www.youtube.com/watch?v=bFhDiZIHlYQ , i just render each scene to the screen with GraphicsDevice.BlendState = BlendState.Additive; with respect to a light, so scenes just added to each other.
And the question - is it seemed correct or not ?
To answer the question. Sorry no, but I have been corrupted, let me explain.
The human eye is logarithmic. To perceive something as twice as bright we need to square the amount of light coming into our eyes. The same goes for sound.
Yet the RGB values of the screen are linear RGB 128,128,128 is twice as bright as 64,64,64. It has to be linear or our shading algorithms would not work. The fall of would be too quick.
Well no our calculations are wrong but the people who manufacture our screens know this and correct it as best they can..
Rather than me explaining watch this Youtube Computer Color is Broken
So to get the correct mix you need to create the correct mix between the two renders.There is not blend state to solve this so you will have to create a custom pixel shader to do the job. output.color = sqrt( pow ( input1.color , 2 ) + pow ( input2.color , 2) );
It is very subtle, but change the two light source's colours and then switch between linear and logarithmic blending and you will wonder how you ever put up with the broken rendering output in the first place.
I do all rendering and lighting calculations as photon counts, squaring input colours and square rooting output colours.
What about alpha? yep? i am not sure.

Should I use HSV/HSB or RGB and why?

I have to detect leukocytes cells in an image that contains another blood cells, but the differences can be distinguished through the color of cells, leukocytes have more dense purple color, can be seen in the image below.
What color methode I've to use RGB/HSV ? and why ?!
sample image:
Usually when making decisions like this I just quickly plot the different channels and color spaces and see what I find. It is always better to start with a high quality image than to start with a low one and try to fix it with lots of processing
In this specific case I would use HSV. But unlike most color segmentation I would actually use the Saturation Channel to segment the images. The cells are nearly the same Hue so using the hue channel would be very difficult.
hue, (at full saturation and full brightness) very hard to differentiate cells
saturation huge contrast
Green channel, actually shows a lot of contrast as well (it surprised me)
the red and blue channels are hard to actually distinguish the cells.
Now that we have two candidate representations the saturation or the Green channel, we ask which is easier to work with? Since any HSV work involves us converting the RGB image, we can dismiss it, so the clear choice is to simply use the green channel of the RGB image for segmentation.
edit
since you didn't include a language tag I would like to attach some Matlab code I just wrote. It displays an image in all 4 color spaces so you can quickly make an informed decision on which to use. It mimics matlabs Color Thresholder colorspace selection window
function ViewColorSpaces(rgb_image)
% ViewColorSpaces(rgb_image)
% displays an RGB image in 4 different color spaces. RGB, HSV, YCbCr,CIELab
% each of the 3 channels are shown for each colorspace
% the display mimcs the New matlab color thresholder window
% http://www.mathworks.com/help/images/image-segmentation-using-the-color-thesholder-app.html
hsvim = rgb2hsv(rgb_image);
yuvim = rgb2ycbcr(rgb_image);
%cielab colorspace
cform = makecform('srgb2lab');
cieim = applycform(rgb_image,cform);
figure();
%rgb
subplot(3,4,1);imshow(rgb_image(:,:,1));title(sprintf('RGB Space\n\nred'))
subplot(3,4,5);imshow(rgb_image(:,:,2));title('green')
subplot(3,4,9);imshow(rgb_image(:,:,3));title('blue')
%hsv
subplot(3,4,2);imshow(hsvim(:,:,1));title(sprintf('HSV Space\n\nhue'))
subplot(3,4,6);imshow(hsvim(:,:,2));title('saturation')
subplot(3,4,10);imshow(hsvim(:,:,3));title('brightness')
%ycbcr / yuv
subplot(3,4,3);imshow(yuvim(:,:,1));title(sprintf('YCbCr Space\n\nLuminance'))
subplot(3,4,7);imshow(yuvim(:,:,2));title('blue difference')
subplot(3,4,11);imshow(yuvim(:,:,3));title('red difference')
%CIElab
subplot(3,4,4);imshow(cieim(:,:,1));title(sprintf('CIELab Space\n\nLightness'))
subplot(3,4,8);imshow(cieim(:,:,2));title('green red')
subplot(3,4,12);imshow(cieim(:,:,3));title('yellow blue')
end
you could call it like this
rgbim = imread('http://i.stack.imgur.com/gd62B.jpg');
ViewColorSpaces(rgbim)
and the display is this
in DIP and CV is this always a valid question
But it has no universal answer because each task is unique so use what is better suited for it. To choose correctly you need to know the pros/cons of each so here is some summary:
RGB
this is easy to handle and you can easyly access r,g,b bands. For many cases is better to check just single band instead of whole color or mix the colors to emphasize wanted feature or even dampening unwanted one. It is hard to compare colors in RGB due to intensity encoded into bands directly. To remedy that you can use normalization but that is slow (need per pixel sqrt). You can do arithmetics on RGB colors directly.
Example of task better suited for RGB:
finding horizont in high altitude photo
HSV
is better suited for color recognition because CV algorithms using HSV has very similar visual perception to human perception so if you want to recognize areas of distinct colors HSV is better. The conversion between RGB/HSV takes a bit of time which can be for big resolutions or hi fps apps a problem. For standard DIP/CV tasks is this usually not the case.
Example of task better suited for HSV:
Compare RGB colors
Take a look at:
HSV histogram
to see the distinct color separation in HSV. The segmentation of image based on color is easy on HSV. You can not do arithmetics on HSV colors directly instead need to convert to RGB and back

Resources