Modify Alpha based on RGB values with Accelerate Framework - ios

Is it possible to adjust the alpha using the Accelerate framework based on the pixels RGB value?
Specifically I want to set the Alpha to 0 if the color is black (RGB 0/0/0)

Not with Accelerate. In CoreGraphics, you can set a masking color, if you like.
https://developer.apple.com/library/mac/documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_images/dq_images.html#//apple_ref/doc/uid/TP30001066-CH212-CJBHCADE
Strictly speaking, if you set a masking color on a CGImageRef and then decode it to pixels with vImageBufer_InitWithCGImage, it should do that which /might/ qualify. However, CG is doing the masking work in that case.
You can file a Radar asking for it. It hasn't been a priority so far because the alpha you get is not anti-aliased.
typedef __attribute__ ((ext_vector_type( 4),__aligned__( 16))) uint32_t uint4;
// ARGB example (on little endian processor):
// uint4 result = maskByColor( pixels, (uint4)0, (uint4) 0x000000ff );
uint4 maskByColor( uint4 fourPixels, uint4 maskColor, uint4 alphaMask ){
return fourPixels & ~(maskColor == (fourPixels & ~alphaMask));
}

Related

JavaCV: the best way to insert bit mask to color image

I have a binary mask, created by opencv (8-bit opencv_core.Mat from org.bytedeco.javacpp, 0 for background, 255 for objects), and some other matrix "source", color or grayscale, any depth (8-bit, 16-bit, float...)
I need to "draw" the mask on the source matrix by white color: pixels 255 from the mask must become "white" on the source matrix.
What is the simplest way to do this IN JAVA?
I do the following:
if (source.depth() != opencv_core.CV_8U) {
mask.convertTo(mask, source.depth(), OTools.maxPossibleValue(source) / 255.0, 0.0);
}
if (source.channels() > 1) {
opencv_imgproc.cvtColor(mask, mask, opencv_imgproc.CV_GRAY2BGR, source.channels());
}
opencv_core.bitwise_or(source, mask, mask);
(maxPossibleValue returns 255 for CV_8U, 65535 for CV_16U, 1.0 for floating-point). But I hope, there is more obvious and universal way. For example, what will be if source is not BGR, but BGRA or other color model?

Histogram Matching

I am using calcBackProject to find an object in a frame and it works somehow well scanning all the frame. but I need to enhance it
In my code at some point I have a motion detection mask and based on it I generated contours for candidate objects (objects that move and might be the target)
could I utilise this to calculate histogram for each contour and match it to the histogram of the target?
how to calculate histogram for each contour?
calcHist accepts mask but how to pass the contour as a mask
-how to match?
Convert your contour to a mask and use the mask in calcHist.
In C++ it would be done like this :
/**
* Converts a contour to a binary mask.
* The parameter mask should be a matrix of type CV_8UC1 with proper
* size to hold the mask.
* #param contour The contour to convert.
* #param mask The Mat where the mask will be written. Must have proper size
* and type before callign convertContourToMask.
*/
void convertContourToMask( const std::vector<cv::Point>& contour, cv::Mat& mask )
{
std::vector<std::vector<cv::Point>> contoursVector;
contoursVector.push_back( contour );
cv::Scalar white = cv::Scalar(255);
cv::Scalar black = cv::Scalar(0);
mask.setTo(black);
cv::drawContours(mask, contoursVector, -1, white, CV_FILLED);
}

color a grayscale image with opencv

i'm using openNI for some project with kinect sensor. i'd like to color the users pixels given with the depth map. now i have pixels that goes from white to black, but i want from red to black. i've tried with alpha blending, but my result is only that i have pixels from pink to black because i add (with addWeight) red+white = pink.
this is my actual code:
layers = device.getDepth().clone();
cvtColor(layers, layers, CV_GRAY2BGR);
Mat red = Mat(240,320, CV_8UC3, Scalar(255,0,0));
Mat red_body; // = Mat::zeros(240,320, CV_8UC3);
red.copyTo(red_body, device.getUserMask());
addWeighted(red_body, 0.8, layers, 0.5, 0.0, layers);
where device.getDepth() returns a cv::Mat with depth map and device.getUserMask() returns a cv::Mat with user pixels (only white pixels)
some advice?
EDIT:
one more thing:
thanks to sammy answer i've done it. but actually i don't have values exactly from 0 to 255, but from (for example) 123-220.
i'm going to find minimum and maximum via a simple for loop (are there better way?), and how can i map my values from min-max to 0-255 ?
First, OpenCV's default color format is BGR not RGB. So, your code for creating the red image should be
Mat red = Mat(240,320, CV_8UC3, Scalar(0,0,255));
For red to black color map, you can use element wise multiplication instead of alpha blending
Mat out = red_body.mul(layers, 1.0/255);
You can find the min and max values of a matrix M using
double minVal, maxVal;
minMaxLoc(M, &minVal, &maxVal, 0, 0);
You can then subtract the minValue and scale with a factor
double factor = 255.0/(maxVal - minVal);
M = factor*(M -minValue)
Kinda clumsy and slow, but maybe split layers, copy red_body (make it a one channel Mat, not 3) to the red channel, merge them back into layers?
Get the same effect, but much faster (in place) with reshape:
layers = device.getDepth().clone();
cvtColor(layers, layers, CV_GRAY2BGR);
Mat red = Mat(240,320, CV_8UC1, Scalar(255)); // One channel
Mat red_body;
red.copyTo(red_body, device.getUserMask());
Mat flatLayer = layers.reshape(1,240*320); // presumed dimensions of layer
red_body.reshape(0,240*320).copyTo(flatLayer.col(0));
// layers now has the red from red_body

how to separate BGR components of a pixel in color image using openCV

Since each pixel memory contains 8 bit for each component Blue,Green and Red. So how can I separate these components from Image or Image Matrix. As
int Blue = f(Image(X,y));// (x,y) = Coordinate of a pixel of Image
similarly, for red and green.
So what should be function f and 2D matrix Image;
Thanks in advance
First off, you must go through the basics of OpenCV and turn your attention towards other parts of image processing. What you ask for is pretty basic and assuming you will be using OpenCV 2.1 and higher,
cv::Mat img = Read the image off the disk or do something to fill the image.
To access the RGB values
img.at<cv::Vec3b>(x,y);
But would give the values in reverse that is BGR. So make sure you note this.
Basically a cv::Vec3b type that is accessed.
img.at<cv::Vec3b>(x,y)[0];//B
img.at<cv::Vec3b>(x,y)[1];//G
img.at<cv::Vec3b>(x,y)[2];//R
or
Vec3f pixel = img.at<Vec3f>(x, y);
int b = pixel[0];
int g = pixel[1];
int r = pixel[2];
Now onto splitting the image into RGB channels you can use the following
Now down to primitive C style of OpenCV (There C and C++ style supported)
You can use the cvSplit function
IplImage* rgb = cvLoatImage("C://MyImage.bmp");
//now create three single channel images for the channel separation
IplImage* r = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
IplImage* g = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
IplImage* b = cvCreateImage( cvGetSize(rgb), rgb->depth,1 );
cvSplit(rgb,b,g,r,NULL);
OpenCV 2 CookBook Is one of the best books on OpenCV. Will help you alot.

How to convert captured bitmap to 8 bit image as gray scale?

I am trying to convert the camera captured image to 8 bit image. And that should be grayscale image.
I searched in forums but could able to find the way to convert to 8 bit image.
Any help or suggestion will be help ful to me.
Thanks....
You have given too little information. First of all, what is the image format your camera delivers? Is it some RAW format, jpeg, or what else?
Doing it programmatically (using C for the example):
The best way to go was to use some image loading library (e.g. SDL_image), and load the image into memory, uncompressed RGB being the target format. Once you have an uncompressed RGB image format, you could do something like
// bufPtr points to the start of the memory containing the bitmap
typedef unsigned char byte;
struct rgb { byte red, green blue; } * colorPtr = bufPtr;
for (int i = 0; i < bufSize; i++, bufPtr++) {
byte gray = (unsigned char) (((float) bufPtr->red * 0.3f +
(float) bufPtr->green * 0.59f +
(float) bufPtr->blue * 0.11f)) / 3.0f * 255.0f + 0.5f);
bufPtr->red = bufPtr->green = bufPtr->blue = gray;
}
If you don't want to code, you could e.g. use GIMP, load your image and apply desaturate from the color menu. You can install the ufraw plugin for GIMP to load images in RAW format in it. If you want to store the entire color information in 8 bits (and not use 8 bits per color channel), there is another option in GIMP to decrease the color depth.

Resources