Can anybody tell me the correct java code for this c++ code snippet:
output.at(x, y) = target.at(dx, dy);
I have tried this java code and they are displacing pixel but not showing image clearly :
output.put(x, y, target.get(dx, dy));
For one channel images e.g. grey-scale; 0 ~ 255
Getting a pixel value
double pixelValue = image.get(i,j)[0];
Setting a pixel value
image.put(i,j,230);
For 3 channel images e.g. RGB (3 values 0 ~ 255)
Getting a pixel (double[] array will have 3 values)
double[] pixelValue = image.get(i,j);
Setting a pixel with 3 RGB values
image.put(i,j,255,250,100); // yellow color
Related
Here is the picture in grayscale mode:
if I apply a Thresholding and set threshold to 0. According to my understanding, the thesholded image will be mostly white. but the result is opposite.
Result is:
I also tried this:
build a image and set all pixel to 255. then apply the 0 threshold thresholding, the returned image is all 255.
The question is:
in the picture is mostly zero (black) after apply thresholding.
Here are the code:
IplImage* g_image = NULL;
IplImage* g_gray = NULL;
int g_thresh = 100;
CvMemStorage* g_storage = NULL;
void on_tracker(int){
if(g_storage == NULL){
g_gray = cvCreateImage(cvGetSize(g_image), 8, 1);
g_storage = cvCreateMemStorage(0);
}else{
cvClearMemStorage(g_storage);
}
CvSeq* contours = 0;
cvCvtColor(g_image, g_gray, CV_BGR2GRAY);
cvNamedWindow("Gray");
cvShowImage("Gray", g_gray);
cvThreshold(g_gray, g_gray, g_thresh, 255, CV_THRESH_BINARY);
cvFindContours(g_gray, g_storage, &contours);
cvShowImage("Contours", g_gray);
}
int main(int argc, char** argv){
if( argc !=2 || !(g_image = cvLoadImage(argv[1]))){
return -1;
}
cvNamedWindow("Contours", CV_WINDOW_AUTOSIZE);
cvCreateTrackbar(
"Threshold",
"Contours",
&g_thresh,
255,
on_tracker
);
on_tracker(0);
cvWaitKey();
return 0;
}
Have a read of the different types of thresholding available to you in the documentation.
Starting with a 1D 'image' with a range of values (the black line) and threshold (the blue line):
...we can visualise the outcome of the different modes:
Threshold Binary
Threshold Binary Inverted
Truncate
Threshold to Zero
Threshold to Zero Inverted
Please update your question with your code so we know what mode you're using if this answer doesn't help already ;)
The basic Thresholding is to check the pixels value (say from 0 to 255) to be above the Threshold value and to assign to the pixel a value of maximum value (high intensity: black) this called Binary Thresholding.
In your case, when setting a value of 0 to the threshold, you actually filtering all your pixels since all of them (the low intensities and the higher intensities) have values above zero (0).
Maybe you would like to make a brighter picture - in this case use Inverted Binary Thresholding: in this case, you will get white picture when value is 0.
Accoring to #Miki's comments. this is caused by C API. I tried the same process with python API. the result is normal:
if I do thresholding with 0 threshold, most of pixel will be set to 255.
consider the an image as [ 1 2 3; 4 5 6 ; 7 8 9] matrix. How we can convert given image to grayscale image. I know that we need to get r,g,b values of each pixel. And using 0.2*R+0.7*G+0.1*B formula we can get the grayscale values of each pixel.But how can I get the r,g,b values of each pixel.
Or is there a completely another method the convert given image to grayscale?
So far, you need to split each 24 bit pixel value to R,G,B component. As an example in matlab:
% If x is a 24 bit string in base 2
r_binary = x(1:8);
g_binary = x(9:16);
b_binary = x(17:24);
r_value = base2dec(r_binary,2);
g_value = base2dec(g_binary,2);
b_value = base2dec(b_binary,2);
% If x is a decimal value
r_value = rem(x,2^8);
g_value = rem(bitshift(x,-8),2^8);
b_value = rem(bitshift(x,-16),2^8);
I am looking to analyze the most dominant color in a UIImage on iOS (color present in the most pixels) and I stumbled upon Core Image's filter based API, particularly CIAreaHistogram.
It seems like this filter could probably help me but I am struggling to understand the API. Firstly it says the output of the filter is a one-dimensional image which is the length of your input-bins and one pixel in height. How do I read this data? I basically want to figure out the color-value with the highest frequency so I am expecting the data to contain some kind of frequency count for each color, its not clear to me how this one-dimensional image would represent that because it does not really explain the data I can expect inside this 1-d image. And if its truly a histogram why would it not return a data-structure representing that like a dictionary
Second, in the API it asks for a number of bins? What should that input be? If I want an exact analysis would the input bin parameter be the color-space of my image? What does making the bin value smaller do, I would imagine it just approximates nearby colors via Euclidean distance to the nearest bin. If this is the case will that not yield exact histogram results, why would anyone want to do that?
Any input on the above two questions from an API perspective would help me greatly
Ian Ollmann's idea of calculating the histogram just for the hue is really neat and can be done with a simple color kernel. This kernel returns a monochrome image of just the hue of an image (based on this original work)
let shaderString = "kernel vec4 kernelFunc(__sample c)" +
"{" +
" vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);" +
" vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));" +
" vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));" +
" float d = q.x - min(q.w, q.y);" +
" float e = 1.0e-10;" +
" vec3 hsv = vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);" +
" return vec4(vec3(hsv.r), 1.0);" +
"}"
let colorKernel = CIColorKernel(string: shaderString)
If I get the hue of an image of a blue sky, the resulting histogram looks like this:
...while a warm sunset gives a histogram like this:
So, that looks like a good technique to get the dominant hue of an image.
Simon
CIAreaHistogram returns an image where the reg, green, blue and alpha values of each of the pixels indicates the frequency of that tone in the image. You can render that image to an array of UInt8 to look at the histogram data. There's also an undocumented outputData value:
let filter = CIFilter(
name: "CIAreaHistogram",
withInputParameters: [kCIInputImageKey: image])!
let histogramData = filter.valueForKey("outputData")
However, I've found vImage to be a better framework for working with histograms. First off, you need to create a vImage image format:
var format = vImage_CGImageFormat(
bitsPerComponent: 8,
bitsPerPixel: 32,
colorSpace: nil,
bitmapInfo: CGBitmapInfo(
rawValue: CGImageAlphaInfo.PremultipliedLast.rawValue),
version: 0,
decode: nil,
renderingIntent: .RenderingIntentDefault)
vImage works with image buffers that can be created from CGImage rather than CIImage instances (you can create one with the createCGImage method of CIContext. vImageBuffer_InitWithCGImage will create an image buffer:
var inBuffer: vImage_Buffer = vImage_Buffer()
vImageBuffer_InitWithCGImage(
&inBuffer,
&format,
nil,
imageRef,
UInt32(kvImageNoFlags))
Now to create arrays of Uint which will hold the histogram values for the four channels:
let red = [UInt](count: 256, repeatedValue: 0)
let green = [UInt](count: 256, repeatedValue: 0)
let blue = [UInt](count: 256, repeatedValue: 0)
let alpha = [UInt](count: 256, repeatedValue: 0)
let redPtr = UnsafeMutablePointer<vImagePixelCount>(red)
let greenPtr = UnsafeMutablePointer<vImagePixelCount>(green)
let bluePtr = UnsafeMutablePointer<vImagePixelCount>(blue)
let alphaPtr = UnsafeMutablePointer<vImagePixelCount>(alpha)
let rgba = [redPtr, greenPtr, bluePtr, alphaPtr]
let histogram = UnsafeMutablePointer<UnsafeMutablePointer<vImagePixelCount>>(rgba)
The final step is to perform the calculation, which will populate the four arrays, and free the buffer's data:
vImageHistogramCalculation_ARGB8888(&inBuffer, histogram, UInt32(kvImageNoFlags))
free(inBuffer.data)
A quick check of the alpha array of an opaque image should yield 255 zeros with the final value corresponding to the number of pixels in the image:
print(alpha) // [0, 0, 0, 0, 0 ... 409600]
A histogram won't give you the dominant color from a visual perspective: an image which is half yellow {1,1,0} and half black {0,0,0} will give the same results as an image which is half red {1,0,0} and held green {0,1,0}.
Hope this helps,
Simon
One problem with the histogram approach is that you lose correlation between the color channels. That is, half your image could be magenta and half yellow. You will find a red histogram that is all in the 1.0 bin, but the blue and green bins would be evenly split between 0.0 and 1.0 with nothing in between. Even though you can be quite sure that red is bright, you won't be able to say much about what the blue and green component should be for the "predominant color"
You could use a 3D histogram with 2**(8+8+8) bins, but this is quite large and you will find the signal is quite sparse. By happenstance three pixels might land in one bin and have no two the same elsewhere, even though many users could tell you that there is a predominant color and it has nothing to do with that pixel.
You could make the 3D histogram a lot lower resolution and have (for example) just 16 bins per color channel. It is much more likely that bins will have a statistically meaningful population count this way. This should give you a starting point to find a mean for a local population of pixels in that bin. If each bin had a count and a {R,G,B} sum, then you could quickly find the mean color for pixels in that bin once you had identified the most popular bins. This method is still subject to some influence from the histogram grid. You will be more likely to identify colors in the middle of a grid cell than at the edges. Populations may span multiple grid cells. Something like kmeans might be another method.
If you just want predominant hue, then conversion to a color space like HSV followed by a histogram of hue would work.
I'm not aware of any filters in vImage, CI or MetalPerformanceShaders to do these things for you. You can certainly write code in either the CPU or Metal to do it without a lot of trouble.
I converted a png (RGBA) to jpeg (RGB) using libpng to decode the png file and applying png_set_strip_alpha to ignore alpha channels. But after conversion the output image has many spots. I think the reason is that the original image has areas whose alpha was 0, which hides the pixel regardless of its RGB value. And when I strip alpha(ie set alpha = 1), the pixel shows. So I think just using png_set_strip_alpha is not the right solution. Should I write a method myself, or is there already a way to achieve this in libpng?
There is no method for that. If you drop alpha channel libpng will give you raw RGB channels and this will "uncover" colors that were previously invisible.
You should load RGBA image and convert it to RGB yourself. The simplest way is to multiply RGB values by alpha.
This will convert RGBA bitmap to RGB in-place:
for(int i=0; i < width*height; i++) {
int r = bitmap[i*4+0],
g = bitmap[i*4+1],
b = bitmap[i*4+2],
a = bitmap[i*4+3];
bitmap[i*3+0] = r * a / 255;
bitmap[i*3+1] = g * a / 255;
bitmap[i*3+2] = b * a / 255;
}
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.