I’m having troubles with gocv function Normalize. that in the documentation goes like that.
func Normalize(src Mat, dst *Mat, alpha float64, beta float64, typ NormType)
I’m calling this at my code and get a segmentation error in response. Can you help me fix this call?
package main
import (
“./imageprocessing”
“gocv.io/x/gocv”
// “fmt”
)
/** CovarFlags
// CovarScrambled indicates to scramble the results.
CovarScrambled CovarFlags = 0
// CovarNormal indicates to use normal covariation.
CovarNormal CovarFlags = 1
// CovarUseAvg indicates to use average covariation.
CovarUseAvg CovarFlags = 2
// CovarScale indicates to use scaled covariation.
CovarScale CovarFlags = 4
// CovarRows indicates to use covariation on rows.
CovarRows CovarFlags = 8
// CovarCols indicates to use covariation on columns.
CovarCols CovarFlags = 16
**/
func main() {
var size int
var normtype gocv.NormType = gocv.NormMinMax
size = imageprocessing.FolderLength("./imageprocessing/Images/danger")
Images := make([]gocv.Mat,size)
GLCMs := make([]gocv.Mat,size)
normalizedGLCMs := make([]gocv.Mat,size)
means := make([]gocv.Mat,size)
imageprocessing.ReadFolder(Images,"./imageprocessing/Images/danger",true,false,false)
//GroupGLCM(Images []gocv.Mat, GLCMs []gocv.Mat, means []gocv.Mat, show bool)
imageprocessing.GroupGLCM(Images, GLCMs, means, false)
//func Normalize(src Mat, dst *Mat, alpha float64, beta float64, typ NormType)
//min value of dst is alpha and max value of dst is beta
for i := 0; i < size; i++ {
gocv.Normalize(GLCMs[i], &normalizedGLCMs[i], 0.0, 255.0, normtype )
//imageprocessing.ShowImage("normalizedGLCMs", normalizedGLCMs[i], 100)
}
Related
So I'm aware how you can use loadPixels() and updatePixels() to alter the individual pixels of the main canvas as though it were a bitmap. Is there any similar technique for accessing the pixels of a createGraphics() object? Or do I have to write it to the canvas then manipulate that?
Or am I supposed to use a drawingContext object somehow?
If you want to manipulate pixels use createImage()
If you want to draw easily using the graphics functions use createGraphics() and loadPixels() / reading pixels[] should work:
var buffer;
function setup() {
createCanvas(400, 400);
buffer = createGraphics(10,10);
buffer.ellipse(5,5,5);
buffer.loadPixels();
console.log(buffer.pixels);
}
function draw() {
background(220);
image(buffer,0,0,400,400);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
You can of course write pixels into PGraphics too if you want.
PImage is a bit lighter weight if you don't need the drawing functionality and just need pixels.
Here's an example:
var buffer;
function draw() {
background(220);
image(buffer,0,0,400,400);
}
function setup() {
createCanvas(400, 400);
buffer = createGraphics(10,10);
buffer.ellipse(5,5,5);
buffer.loadPixels();
// print pixels (list of bytes in order (e.g. [r0,g0,b0,a0,r1,g1,b1,a1,...])
console.log(buffer.pixels);
var gradientW = 3;
var gradientH = 3;
for(var y = 0; y < gradientH; y++){
for(var x = 0; x < gradientH; x++){
// calculate 1D index from x,y
let pixelIndex = x + (y * buffer.width);
// note that as opposed to Processing Java, p5.Image is RGBA (has 4 colour channels, hence the 4 bellow)
// and the pixels[] array is equal to width * height * 4 (colour cannels)
// therefore the index is also * 4
let rIndex = pixelIndex * 4;
console.log('x',x,'y',y,'pixelIndex',pixelIndex,'red index',rIndex);
// access and assign red
buffer.pixels[rIndex] = round(map(x,0,3,0,255));
// access and assign green
buffer.pixels[rIndex + 1] = round(map(y,0,3,0,255));
// access and assign blue
buffer.pixels[rIndex + 2] = 255 - buffer.pixels[rIndex] + buffer.pixels[rIndex + 1]
// access and assign alpha
buffer.pixels[rIndex + 3] = 255;
}
}
buffer.updatePixels();
}
function draw() {
background(220);
image(buffer,0,0,width,height);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
I am trying to make a colored waveform using the output of the following code. But when I run it, I only get certain numbers (see the freq variable, it uses the bin size, frame rate and index to make these frequencies) as output frequencies. I'm no math expert, even though I cobbled this together from existing code and answers.
//
// colored_waveform.c
// MixDJ
//
// Created by Jonathan Silverman on 3/14/19.
// Copyright © 2019 Jonathan Silverman. All rights reserved.
//
#include "colored_waveform.h"
#include "fftw3.h"
#include <math.h>
#include "sndfile.h"
//int N = 1024;
// helper function to apply a windowing function to a frame of samples
void calcWindow(double* in, double* out, int size) {
for (int i = 0; i < size; i++) {
double multiplier = 0.5 * (1 - cos(2*M_PI*i/(size - 1)));
out[i] = multiplier * in[i];
}
}
// helper function to compute FFT
void fft(double* samples, fftw_complex* out, int size) {
fftw_plan p;
p = fftw_plan_dft_r2c_1d(size, samples, out, FFTW_ESTIMATE);
fftw_execute(p);
fftw_destroy_plan(p);
}
// find the index of array element with the highest absolute value
// probably want to take some kind of moving average of buf[i]^2
// and return the maximum found
double maxFreqIndex(fftw_complex* buf, int size, float fS) {
double max_freq = 0;
double last_magnitude = 0;
for(int i = 0; i < (size / 2) - 1; i++) {
double freq = i * fS / size;
// printf("freq: %f\n", freq);
double magnitude = sqrt(buf[i][0]*buf[i][0] + buf[i][1]*buf[i][1]);
if(magnitude > last_magnitude)
max_freq = freq;
last_magnitude = magnitude;
}
return max_freq;
}
//
//// map a frequency to a color, red = lower freq -> violet = high freq
//int freqToColor(int i) {
//
//}
void generateWaveformColors(const char path[]) {
printf("Generating waveform colors\n");
SNDFILE *infile = NULL;
SF_INFO sfinfo;
infile = sf_open(path, SFM_READ, &sfinfo);
sf_count_t numSamples = sfinfo.frames;
// sample rate
float fS = 44100;
// float songLengLengthSeconds = numSamples / fS;
// printf("seconds: %f", songLengLengthSeconds);
// size of frame for analysis, you may want to play with this
float frameMsec = 5;
// samples in a frame
int frameSamples = (int)(fS / (frameMsec * 1000));
// how much overlap each frame, you may want to play with this one too
int frameOverlap = (frameSamples / 2);
// color to use for each frame
// int outColors[(numSamples / frameOverlap) + 1];
// scratch buffers
double* tmpWindow;
fftw_complex* tmpFFT;
tmpWindow = (double*) fftw_malloc(sizeof(double) * frameSamples);
tmpFFT = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * frameSamples);
printf("Processing waveform for colors\n");
for (int i = 0, outptr = 0; i < numSamples; i += frameOverlap, outptr++)
{
double inSamples[frameSamples];
sf_read_double(infile, inSamples, frameSamples);
// window another frame for FFT
calcWindow(inSamples, tmpWindow, frameSamples);
// compute the FFT on the next frame
fft(tmpWindow, tmpFFT, frameSamples);
// which frequency is the highest?
double freqIndex = maxFreqIndex(tmpFFT, frameSamples, fS);
printf("%i: ", i);
printf("Max freq: %f\n", freqIndex);
// map to color
// outColors[outptr] = freqToColor(freqIndex);
}
printf("Done.");
sf_close (infile);
}
Here is some of the output:
2094216: Max freq: 5512.500000
2094220: Max freq: 0.000000
2094224: Max freq: 0.000000
2094228: Max freq: 0.000000
2094232: Max freq: 5512.500000
2094236: Max freq: 5512.500000
It only shows certain numbers, not a wide variety of frequencies like it maybe should. Or am I wrong? Is there anything wrong with my code you guys can see? The color stuff is commented out because I haven't done it yet.
The frequency resolution of an FFT is limited by the length of the data sample you have. The more samples you have, the higher the frequency resolution.
In your specific case you chose frames of 5 milliseconds, which is then transformed to a number of samples on the following line:
// samples in a frame
int frameSamples = (int)(fS / (frameMsec * 1000));
This corresponds to only 8 samples at the specified 44100Hz sampling rate. The frequency resolution with such a small frame size can be computed to be
44100 / 8
or 5512.5Hz, a rather poor resolution. Correspondingly, the observed frequencies will always be one of 0, 5512.5, 11025, 16537.5 or 22050Hz.
To get a higher resolution you should increase the number of samples used for analysis by increasing frameMsec (as suggested by the comment "size of frame for analysis, you may want to play with this").
I'm trying to write a function in Scilab to display images.
I'm dealing with images as lists of matrices, and then converting the list to a hypermatrix inside the function. However, the code does not seem to work for images of the type uint16 or uint32.
This is the code I've been working on:
imshow()
function[] =imshow(Image)
global TYPE_DOUBLE; //retrieving list and creating 3 dimensional matrix out of it
dimensions=size(Image)
MaxUInt8 = 2 ^ 8 - 1;
MaxGrayValue = MaxUInt8; //changed from MaximumGrayValue
if dimensions==3 then
matSize=size(Image(1));
r=matrix(Image(1),matSize(1),matSize(2));
g=matrix(Image(2),matSize(1),matSize(2));
b=matrix(Image(3),matSize(1),matSize(2));
z(:,:,1)=uint8(r); //Since Matplot is not working with uint16 and uint32, convert every image to a
z(:,:,2)=uint8(g); //8 bit palette.
z(:,:,3)=uint8(b); //Note: this will affect the color depth.
[NumberOfRows NumberOfColumns NumberOfChannels] = size(z);
NumberOfPixels = NumberOfRows * NumberOfColumns;
Sample = z(1);
//printf("\nType of Sample: ");
//printf(typeof(Sample)); //DEBUG:
//printf("\n");
if type(Sample) == 1 then //type 1 = real/complex matrix of double
ColorMap = matrix(z, NumberOfPixels, NumberOfChannels);
disp(ColorMap);
else
TypeName = typeof(Sample)
select TypeName
case 'uint8'
MaxGrayValue = 2 ^ 8 - 1;
//printf("uint8\t%d", MaxGrayValue); //DEBUG:
case 'uint16'
MaxGrayValue = 2 ^ 16 - 1;
//ColorMap = double(matrix(z, NumberOfPixels, NumberOfChannels)) / MaxGrayValue;
//printf("uint16\t%d", MaxGrayValue); //DEBUG:
case 'uint32'
MaxGrayValue = 2 ^ 32 - 1;
//ColorMap = double(matrix(z, NumberOfPixels, NumberOfChannels)) / MaxGrayValue;
//printf("uint32\t%d", MaxGrayValue); //DEBUG:
end;
ColorMap = double(matrix(z, NumberOfPixels, NumberOfChannels)) / MaxGrayValue;
printf("\nCreated colormap with MaxGrayValue = %d\n", MaxGrayValue); //DEBUG:
end;
Img=z;
//Grayscale
elseif dimensions==1 then
matSize = size(Image(1));
Img=matrix(Image(1),matSize(1),matSize(2));
Img=Img';
select typeof(Img)
case 'uint8'
MaxGrayValue = MaxUInt8;
case 'uint16'
MaxGrayValue = max(Image(:)) ;
case 'uint32'
MaxGrayValue = max(Image(:));
end;
ColorMap = graycolormap(double(MaxGrayValue + 1)); //changed from MaximumGrayValue
end;
show(Img,ColorMap);
endfunction
show()
function[] =show(Img,ColorMap)
FigureHandle = gcf();
drawlater();
FigureHandle.color_map = ColorMap
FigureHandle.background = -2; // sets the background to white
FigureHandle.figure_name = "Title";
[NumberOfRows NumberOfColumns] = size(Img);
FigureHandle.axes_size = [NumberOfColumns NumberOfRows];
delete(gca()); // previous image is deleted
Diagram = gca();
[NumberOfRows NumberOfColumns] = size(Img);
Diagram.data_bounds = [1, 1; NumberOfColumns, NumberOfRows];
Diagram.axes_visible = ['off' 'off' 'off'];
Diagram.isoview = 'on';
Options = '082'; // Box is drawn around image.
//printf("\nGiven to Matplot: "); //DEBUG:
//printf(typeof(Img)); //DEBUG:
Matplot(Img, Options);
drawnow();
endfunction
The error I'm getting is:
!--error 202
Matplot: Wrong type for input argument #1: A real or integer expected.
at line 22 of function show called by :
at line 67 of function imshow called by :
imshow(a);
Any help would be great.
It seems that OpenCV and matplotlib all cannot support imshow of uint16 or uint32, so the images will be converted to uint8 when shown.
I'm having a problem with the implementation of multiple kernel functions in Metal in combination with Swift.
My target is to implement a block-wise DCT transformation over an image. The DCT is implemented with two matrix multiplications.
J = H * I * H^-1
The following code shows the kernel functions itself and the used calls in the swift code. If I run each kernel function alone it works but i can't manage to hand over the write buffer from the first kernel function to the second function. The second function therefore always returns a buffer filled with just 0.
All the image input and output buffers are 400x400 big with RGB (16-bit Integer for each component). The matrices are 8x8 16-bit Integers.
Is there a special command needed to synchronize the buffer read and write accesses of the different kernel functions? Or am I doing something else wrong?
Thanks for your help
shaders.metal
struct Image3D16{
short data[400][400][3];
};
struct Matrix{
short data[8 * 8];
};
kernel void dct1(device Image3D16 *inputImage [[buffer(0)]],
device Image3D16 *outputImage [[buffer(1)]],
device Matrix *mult [[buffer(2)]],
uint2 gid [[thread_position_in_grid]],
uint2 tid [[thread_position_in_threadgroup]]){
int red = 0, green = 0, blue = 0;
for(int x=0;x<8;x++){
short r = inputImage->data[gid.x-tid.x + x][gid.y][0];
short g = inputImage->data[gid.x-tid.x + x][gid.y][1];
short b = inputImage->data[gid.x-tid.x + x][gid.y][2];
red += r * mult->data[tid.x*8 + x];
green += g * mult->data[tid.x*8 + x];
blue += b * mult->data[tid.x*8 + x];
}
outputImage->data[gid.x][gid.y][0] = red;
outputImage->data[gid.x][gid.y][1] = green;
outputImage->data[gid.x][gid.y][2] = blue;
}
kernel void dct2(device Image3D16 *inputImage [[buffer(0)]],
device Image3D16 *outputImage [[buffer(1)]],
device Matrix *mult [[buffer(2)]],
uint2 gid [[thread_position_in_grid]],
uint2 tid [[thread_position_in_threadgroup]]){
int red = 0, green = 0, blue = 0;
for(int y=0;y<8;y++){
short r = inputImage->data[gid.x][gid.y-tid.y + y][0];
short g = inputImage->data[gid.x][gid.y-tid.y + y][1];
short b = inputImage->data[gid.x][gid.y-tid.y + y][2];
red += r * mult->data[tid.y*8 + y];
green += g * mult->data[tid.y*8 + y];
blue += b * mult->data[tid.y*8 + y];
}
outputImage->data[gid.x][gid.y][0] = red;
outputImage->data[gid.x][gid.y][1] = green;
outputImage->data[gid.x][gid.y][2] = blue;
}
ViewController.swift
...
let commandBuffer = commandQueue.commandBuffer()
let computeEncoder1 = commandBuffer.computeCommandEncoder()
computeEncoder1.setComputePipelineState(computeDCT1)
computeEncoder1.setBuffer(input, offset: 0, atIndex: 0)
computeEncoder1.setBuffer(tmpBuffer3D1, offset: 0, atIndex: 1)
computeEncoder1.setBuffer(dctMatrix1, offset: 0, atIndex: 2)
computeEncoder1.dispatchThreadgroups(blocks, threadsPerThreadgroup: dctSize)
computeEncoder1.endEncoding()
let computeEncoder2 = commandBuffer.computeCommandEncoder()
computeEncoder2.setComputePipelineState(computeDCT2)
computeEncoder2.setBuffer(tmpBuffer3D1, offset: 0, atIndex: 0)
computeEncoder2.setBuffer(output, offset: 0, atIndex: 1)
computeEncoder2.setBuffer(dctMatrix2, offset: 0, atIndex: 2)
computeEncoder2.dispatchThreadgroups(blocks, threadsPerThreadgroup: dctSize)
computeEncoder2.endEncoding()
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
I found the error. My kernel function tried to read outside of its allocated memory. The reaction of the metal interface is then to stop the execution of all following commands in the command buffer. Therefore was the output always zero because the computation was never done. The GPU usage of the application drops which can be used for detecting the error.
I have a code snippet from openCV example as follows:
CvScalar sum_line_pixels( IplImage* image, CvPoint pt1, CvPoint pt2 )
{
CvLineIterator iterator;
int blue_sum = 0, green_sum = 0, red_sum = 0;
int count = cvInitLineIterator( image, pt1, pt2, &iterator, 8, 0 );
for( int i = 0; i < count; i++ ){
blue_sum += iterator.ptr[0];
green_sum += iterator.ptr[1];
red_sum += iterator.ptr[2];
CV_NEXT_LINE_POINT(iterator);
/* print the pixel coordinates: demonstrates how to calculate the
coordinates */
{
int offset, x, y;
/* assume that ROI is not set, otherwise need to take it
into account. */
offset = iterator.ptr - (uchar*)(image->imageData);
y = offset/image->widthStep;
x = (offset - y*image->widthStep)/(3*sizeof(uchar)
/* size of pixel */);
printf("(%d,%d)\n", x, y );
}
}
return cvScalar( blue_sum, green_sum, red_sum );
}
I got stuck on the line:
offset = iterator.ptr - (uchar*)(image->imageData);
Iterator structure is:
PCvLineIterator = ^TCvLineIterator;
TCvLineIterator = packed record
ptr: ^UCHAR;
err: Integer;
plus_delta: Integer;
minus_delta: Integer;
plus_step: Integer;
minus_step: Integer;
end;
image->imageData is
imageData: PByte;
Could someone help me convert the offset line to delphi?
Thanks!
The line that calculates offset is simply calculating the number of bytes between the pointers iterator.ptr and image->imageData. Assuming you are using the same variable names a Delphi version of that code would be like this:
offset := PByte(iterator.ptr) - image.ImageData;
However, since you are using an older version of Delphi, the above code will not compile. Older Delphi versions (pre Delphi 2009) don't permit pointer arithmetic on types other than PAnsiChar. So you will need to write it like this:
offset := PAnsiChar(iterator.ptr) - PAnsiChar(image.ImageData);
I suspect that what is confusing you in the C code is (uchar*). That is the C syntax for a type cast.
As an aside, it is a mistake to use packed records for OpenCV structs. If you take a look at the C header files you will see that these structs are not packed. This is benign in the case of CvLineIterator since it has no padding, but you will get caught out somewhere down the line if you get into the bad habit of packing structs that should not be packed.