OpenCV Mat image data structure - objective-c

I have an image that has been processed throw:
//UIImage to Mat
cv::Mat originalMat = [self cvMatFromUIImage:inputImage];
//Grayscale
cv::Mat grayMat;
cv::cvtColor(originalMat, grayMat, CV_RGB2GRAY);
//Blur
cv::Mat gaussMat;
cv::GaussianBlur( grayMat , gaussMat, cv::Size(9, 9), 2, 2 );
//Threshold
cv::threshold(grayMat,tMat,100,255,cv::THRESH_BINARY);
than I want to analyze (calculate qty of white and black points) that belows to line. For instance: I have an image 100x120px and I want to check lines where x = 5 and y = from 0 to 119; and vice versa x = 0..99; y = 5;
so I expect that Mat will contains x - Mat.cols and y - Mat.rows but looks it saves data in another way. for example I've tried to change pixels color that belows to lines but didn't get 2 lines:
for( int x = 0; x < tMat.cols; x++ ){
tMat.at<cv::Vec4b>(5,x)[0] = 100;
}
for( int y = 0; y < tMat.rows; y++ ){
tMat.at<cv::Vec4b>(y,5)[0] = 100;
}
return [self UIImageFromCVMat:tMat];
result for white image:
why I did't get 2 lines? Is it possible to draw\check lines in Mat directly? what if I going to check line that calculates via y = kx + b?

You are accessing the pixel values in the wrong way. You are working with image that only has one channel, that's why you should access pixel values like this:
for (int x = 0; x < tMat.cols; x++){
tMat.at<unsigned char>(5, x) = 100;
}
for (int y = 0; y < tMat.rows; y++){
tMat.at<unsigned char>(y, 5) = 100;
}
The Mat element's type is defined by two properties - the number of channels and the underlying type of data. If you do not know the meaning of those terms, I strongly suggest that you read the documentation for methods cv::Mat::type(), cv::Mat::channels() and cv::Mat::depth().
Two more examples:
mat.at<float>(x, y) = 1.0f; // if mat type is CV_32FC1
mat.at<cv::Vec3b>(x, y) = Vec3b(1, 2, 3); // if mat type is CV_8UC3

Probably an issue with your Mat data types. The output of threshold is a single channel image that is 8-bit or 32-bit (http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#threshold), so you probably should not be setting values with Mat.at<Vec4b>[0].
Here's a function to return the type of your matrix. Usage is in the commented out part. Copied from How to find out what type of a Mat object is with Mat::type() in OpenCV.
std::string type2str(int type){
//string ty = type2str( comparisonResult.type() );
//printf("Matrix: %s %dx%d \n", ty.c_str(), comparisonResult.cols, comparisonResult.rows );
string r;
uchar depth = type & CV_MAT_DEPTH_MASK;
uchar chans = 1 + (type >> CV_CN_SHIFT);
switch ( depth ) {
case CV_8U: r = "8U"; break;
case CV_8S: r = "8S"; break;
case CV_16U: r = "16U"; break;
case CV_16S: r = "16S"; break;
case CV_32S: r = "32S"; break;
case CV_32F: r = "32F"; break;
case CV_64F: r = "64F"; break;
default: r = "User"; break;
}
r += "C";
r += (chans+'0');
return r;}

Related

How to pass a pointer argument to a function without knowing the size to be allocated for that pointer

I know this question is very noob. I am trying to understand how the pointer thing works. I studied basics of C but still did not understand this.
Given this piece of function:
+ (void)nv21ToRgbWithWidth:(unsigned int)width height:(unsigned int)height yuyv:(unsigned char *)yuyv rgb:(unsigned char *)rgb
{
const int nv_start = width * height ;
UInt32 i, j, index = 0, rgb_index = 0;
UInt8 y, u, v;
int r, g, b, nv_index = 0;
for(i = 0; i < height ; i++)
{
for(j = 0; j < width; j ++){
//nv_index = (rgb_index / 2 - width / 2 * ((i + 1) / 2)) * 2;
nv_index = i / 2 * width + j - j % 2;
y = yuyv[rgb_index];
u = yuyv[nv_start + nv_index ];
v = yuyv[nv_start + nv_index + 1];
r = y + (140 * (v-128))/100; //r
g = y - (34 * (u-128))/100 - (71 * (v-128))/100; //g
b = y + (177 * (u-128))/100; //b
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
index = rgb_index % width + (height - i - 1) * width;
rgb[index * 3+0] = b;
rgb[index * 3+1] = g;
rgb[index * 3+2] = r;
rgb_index++;
}
}
}
How am I suppose to know how the unsigned char * for rgb should be initialized before passing in to the function?
I tried calling the function like this:
unsigned char *rgb = NULL;
[MyClass nv21ToRgbWithWidth:imageWidth height:imageHeight yuyv:yuyvValues rgb:rgb];
But the the program crashes on this line:
rgb[index * 3+0] = b;
I see rgb was initialized with NULL, so you can't assign values. So, I thought of initializing an array and pass it to pointer rgb like this:
unsigned char rgbArr[10000];
unsigned char *rgb = rgbArr;
but the function still crashes. I really don't know how should I pass the rgb parameter in this function. Please help me understand this.
The expected size in bytes seems to be at least height*width*3; it might be that allocating such an array as a local variable (as you do with unsigned char rgbArr[10000]) exceeds a stack limit; The program likely crashes in such a case. I'd try to use the heap instead:
unsigned char* rgb = malloc(imageHeight*imageWidth*3);
[MyClass nv21ToRgbWithWidth:imageWidth height:imageHeight yuyv:yuyvValues rgb:rgb];
...
free(rgb);
That is what the malloc(), calloc(), realloc() and free() functions are for. Don't forget to use the free() function to prevent memory leaks... I hope that helps.

Is there anyway I can get every color(rgb) image's pixel matching which depth(ir) image's pixel?

I use Kinect2.0. I already got the intrinsic parameters of the depth camera and color camera, and extrinsic parameters between them.
Now I already know every depth(ir) image's pixel match which color(rgb) image's pixel.
for (int i = 0; i < 424; i++)
{
for (int j = 0; j < 512; j++)
{
fscanf(fp_dp, "%lf", &depthValue);
if (depthValue == 0) continue;
double Pir[3][1] = { j*depthValue, i*depthValue, depthValue };
P_ir = Mat(3, 1, CV_64F, Pir);
P_rgb = Mat(3, 1, CV_64F);
P_rgb = Intrinsic_rgb*(R_ir2rgb*(Intrinsic_ir_inv*P_ir) + T_ir2rgb);
int x = P_rgb.at<double>(0, 0) / depthValue;
int y = P_rgb.at<double>(1, 0) / depthValue;
//printf("(%d,%d)\n", x, y);
if (x < 0 || y < 0 || x >= 1920 || y >= 1080)
{
continue;
}
img_mmap.at<Vec3b>(i, j)[0] = img_rgb.at<Vec3b>(y, x)[0];
img_mmap.at<Vec3b>(i, j)[1] = img_rgb.at<Vec3b>(y, x)[1];
img_mmap.at<Vec3b>(i, j)[2] = img_rgb.at<Vec3b>(y, x)[2];
Color_depth[y][x] = depthValue;
}
fscanf(fp_dp, "\n");
}
fclose(fp_dp);
imwrite(ir_name, img_mmap);
As you can see I want get the color image's depth data. But when I use this method. I just got 512x424 units data. It's not 1920x1080.
So Is there anyway I can know every color(rgb) image's pixel match which depth(ir) image's pixel when I already get the intrinsic parameters of the two cameras and the extrinsic parameters between them?
Use MapColorFrameToDepthSpace.
Remark:
Allocate the depthSpacePoints array before calling this method. It
should have the same number of elements as the color frame has pixels
(1920px by 1080px). Each entry in the filled depthSpacePoints array
contains the depth point to which the corresponding pixel belongs.

Removing the spacing between tiles in tilesheet

So I have an image which contains a tile-sheet, where each tile is approx 16 pixels wide, and high. But there spaced out with a transparent spacer between each tile.
Like so:
But this is ugly, and makes displaying the sprites in the program annoying, not to mention it wastes valuable image space. Is there any easy (Besides me manually using Photoshop to move each individual tile) way to make it look like this?
I looked through Photoshop macros, as-well as other programs and I diden't seem to find anything that would directly do this.
Google also suggests I go to home-depo and get tile caulk remover.
Try this snippet. As you said, it assumes tiles are always going to be 16 pixels. Top left one is in the correct position and a single pixel gap. The script assumes the document will opened with the layer containing your tiles set as the active layer.
#target photoshop
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
var gap = 1;
var tileSize = 16;
var doc = app.activeDocument.duplicate();
var sourceLyr = doc.activeLayer;
var xTilePosition = 0;
var yTilePosition = 0;
for (var x = 0; x < sourceLyr.bounds[2]; x = x+ tileSize + 1 ) {
for (var y = 0; y < sourceLyr.bounds[3]; y = y + tileSize + 1) {
if (x > 0 || y > 0) {
app.activeDocument = doc;
doc.activeLayer = sourceLyr;
selRegion = Array(Array(x, y),
Array(x + tileSize, y),
Array(x + tileSize, y + tileSize),
Array(x, y + tileSize),
Array(x, y))
doc.selection.select(selRegion);
var dx = x - (xTilePosition * tileSize);
var dy = y - (yTilePosition * tileSize);
doc.selection.translate(0 - dx, 0 - dy);
}
yTilePosition ++;
}
xTilePosition++;
yTilePosition = 0;
}

2nd order IIR filter, coefficients for a butterworth bandpass (EQ)?

Important update: I already figured out the answers and put them in this simple open-source library: http://bartolsthoorn.github.com/NVDSP/ Check it out, it will probably save you quite some time if you're having trouble with audio filters in IOS!
^
I have created a (realtime) audio buffer (float *data) that holds a few sin(theta) waves with different frequencies.
The code below shows how I created my buffer, and I've tried to do a bandpass filter but it just turns the signals to noise/blips:
// Multiple signal generator
__block float *phases = nil;
[audioManager setOutputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels)
{
float samplingRate = audioManager.samplingRate;
NSUInteger activeSignalCount = [tones count];
// Initialize phases
if (phases == nil) {
phases = new float[10];
for(int z = 0; z <= 10; z++) {
phases[z] = 0.0;
}
}
// Multiple signals
NSEnumerator * enumerator = [tones objectEnumerator];
id frequency;
UInt32 c = 0;
while(frequency = [enumerator nextObject])
{
for (int i=0; i < numFrames; ++i)
{
for (int iChannel = 0; iChannel < numChannels; ++iChannel)
{
float theta = phases[c] * M_PI * 2;
if (c == 0) {
data[i*numChannels + iChannel] = sin(theta);
} else {
data[i*numChannels + iChannel] = data[i*numChannels + iChannel] + sin(theta);
}
}
phases[c] += 1.0 / (samplingRate / [frequency floatValue]);
if (phases[c] > 1.0) phases[c] = -1;
}
c++;
}
// Normalize data with active signal count
float signalMulti = 1.0 / (float(activeSignalCount) * (sqrt(2.0)));
vDSP_vsmul(data, 1, &signalMulti, data, 1, numFrames*numChannels);
// Apply master volume
float volume = masterVolumeSlider.value;
vDSP_vsmul(data, 1, &volume, data, 1, numFrames*numChannels);
if (fxSwitch.isOn) {
// H(s) = (s/Q) / (s^2 + s/Q + 1)
// http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
// BW 2.0 Q 0.667
// http://www.rane.com/note170.html
//The order of the coefficients are, B1, B2, A1, A2, B0.
float Fs = samplingRate;
float omega = 2*M_PI*Fs; // w0 = 2*pi*f0/Fs
float Q = 0.50f;
float alpha = sin(omega)/(2*Q); // sin(w0)/(2*Q)
// Through H
for (int i=0; i < numFrames; ++i)
{
for (int iChannel = 0; iChannel < numChannels; ++iChannel)
{
data[i*numChannels + iChannel] = (data[i*numChannels + iChannel]/Q) / (pow(data[i*numChannels + iChannel],2) + data[i*numChannels + iChannel]/Q + 1);
}
}
float b0 = alpha;
float b1 = 0;
float b2 = -alpha;
float a0 = 1 + alpha;
float a1 = -2*cos(omega);
float a2 = 1 - alpha;
float *coefficients = (float *) calloc(5, sizeof(float));
coefficients[0] = b1;
coefficients[1] = b2;
coefficients[2] = a1;
coefficients[3] = a2;
coefficients[3] = b0;
vDSP_deq22(data, 2, coefficients, data, 2, numFrames);
free(coefficients);
}
// Measure dB
[self measureDB:data:numFrames:numChannels];
}];
My aim is to make a 10-band EQ for this buffer, using vDSP_deq22, the syntax of the method is:
vDSP_deq22(<float *vDSP_A>, <vDSP_Stride vDSP_I>, <float *vDSP_B>, <float *vDSP_C>, <vDSP_Stride vDSP_K>, <vDSP_Length __vDSP_N>)
See: http://developer.apple.com/library/mac/#documentation/Accelerate/Reference/vDSPRef/Reference/reference.html#//apple_ref/doc/c_ref/vDSP_deq22
Arguments:
float *vDSP_A is the input data
float *vDSP_B are 5 filter coefficients
float *vDSP_C is the output data
I have to make 10 filters (10 times vDSP_deq22). Then I set the gain for every band and combine them back together. But what coefficients do I feed every filter? I know vDSP_deq22 is a 2nd order (butterworth) IIR filter, but how do I turn this into a bandpass?
Now I have three questions:
a) Do I have to de-interleave and interleave the audio buffer? I know setting stride to 2 just filters on channel but how I filter the other, stride 1 will process both channels as one.
b) Do I have to transform/process the buffer before it enters the vDSP_deq22 method? If so, do I also have to transform it back to normal?
c) What values of the coefficients should I set to the 10 vDSP_deq22s?
I've been trying for days now but I haven't been able to figure this on out, please help me out!
Your omega value need to be normalised, i.e. expressed as a fraction of Fs - it looks like you left out the f0 when you calculated omega, which will make alpha wrong too:
float omega = 2*M_PI*Fs; // w0 = 2*pi*f0/Fs
should probably be:
float omega = 2*M_PI*f0/Fs; // w0 = 2*pi*f0/Fs
where f0 is the centre frequency in Hz.
For your 10 band equaliser you'll need to pick 10 values of f0, spaced logarithmically, e.g. 25 Hz, 50 Hz, 100 Hz, 200 Hz, 400 Hz, 800 Hz, 1.6 kHz, 3.2 kHz, 6.4 kHz, 12.8 kHz.

Objective-C: Logic Question

Hey guys, I'm getting a little trouble here. I have a view that makes a grid display. I mean, I have 9 items and sets to display 3 per line. Resulting in 3 lines. That's OK. What I don't understang, it's why always I get a space between them. Sometimes it comes up and on the middle of the lines. The space is equal to one line height.
Check the code:
NSInteger quantidadeDeVideos = [self.videosURL count];
NSInteger contadorDeVideos = 0;
NSInteger idLinha = 0;
NSInteger linha = 1;
NSInteger itemq = 0;
while (contadorDeVideos < quantidadeDeVideos) {
float f;
float g;
// Set the lines
if (itemq < 3) {
itemq++;
}
else {
itemq = 1;
linha++;
}
// This makes the second line multiplies for 150;
if (linha > 1) {
g = 150;
}
else {
g = 0;
}
// Ignore this, this is foi make 1,2,3. Making space between the itens.
if (idLinha > 2) {
idLinha = 0;
}
NSLog(#"%i", foi);
float e = idLinha*250+15;
f = linha*g;
UIImageView *thumbItem = [[UIImageView alloc] init];
thumbItem.frame = CGRectMake(e, f, 231, 140);
UIColor *bkgColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"VideosItemBackground.png"]];
thumbItem.backgroundColor = bkgColor;
thumbItem.opaque = NO;
[self.videosScroll addSubview:thumbItem];
contadorDeVideos++;
idLinha++;
}
This is the result should be:
[][][]
[][][]
[][][]
And this is what I'm getting:
[][][]
[][][]
[][][]
Thanks for all!
When linha is 1, g is 0, making linha * g 0. For the subsequent lines, g is 150, making linha * g == 300 for the second iteration (a jump of 300 over the first), after which it increases by 150 each time. Instead of conditionally setting g each time through, you should just make it a constant 150 and then either use (linha - 1) * g for the value of f or just start linha at 0.
If you want to see how to spot the problem yourself:
Ask yourself, what is going wrong here?
The rectangles are being drawn one row too low
It only happens after the first row
So we look at the line that's responsible for where the rectangles are drawn:
thumbItem.frame = CGRectMake(e, f, 231, 140)
The variable f is the y-coordinate. This has to be what's messed up. Let's see how f is defined:
f = linha*g;
OK, linha is the line number and it's only changed once in the loop without any conditional logic. So the problem is probably g. Let's see how that one is defined:
if (linha > 1) {
g = 150;
}
else {
g = 0;
}
Hey, g changes after the first iteration — precisely when our problem crops up. Let's see what the values of linha*g are:
1 * 0 = 0
2 * 150 = 300 (+300)
3 * 150 = 450 (+150)
4 * 150 = 600 (+150)
Ah-ha — the problem is that setting g to 0 on the first iteration breaks the pattern.