LineIterator in OpenCV C++ in Android - android

I write a program which obtain value of color Asymmetric at lesion.
my program in visual studio Working correctly and I get color Asymmetric. But program in android (use Native) always return 0.
The problem is that points[j] always has same value therefor value of avg_i[i] with avg is equal.
my code:
Mat& srcMat = *(Mat*)src;
Mat& mask_tr = *(Mat*)Mask;
Mat gray;
cvtColor(srcMat, gray, CV_BGR2GRAY);
double summation=0, avg=0, NCD=0, mismatch=0;
double* avg_i = new double[p.size()];
double* ncd = new double[p.size()];
double* XOR_Cs_Cl = new double[p.size()];
int A_x=0, A_t=0;
vector<Vec3b> buf;
for(int i=0; i<p.size(); i++){
LineIterator it(gray, p5, p[i], 8);
vector<Point> points(it.count);
for(int j=0; j<it.count-1; j++)
{
buf.push_back( Vec3b(*it) );
points[j] = it.pos();
it=it++;
summation += int(gray.at<uchar>(points[j].y , points[j].x));
}
avg_i[i] = summation / (it.count-1);
summation = 0;
avg += avg_i[i];
}
avg = avg/p.size();
for(int i=0; i<p.size(); i++){
ncd[i] = avg_i[i] * (100/avg);
A_t += ncd[i];
XOR_Cs_Cl[i] = abs(100 - ncd[i]);
A_x += XOR_Cs_Cl[i];
}
mismatch = (double(A_x) / double(A_t))*100;
delete [] avg_i;
delete [] ncd;
return mismatch;

Related

Tensorflow Lite - Input shape must be 5 dimensional error

I am trying to port a tensorflow model to tensorflow lite to use it in an android application. The conversion is successful and everything runs except for Internal error: Failed to run on the given Interpreter: input must be 5-dimensional. The input in the original model was input_shape=(20, 320, 240, 1), which is 20 320 x 240 grayscale images (therefore ...,1). Here is the important code:
List<Mat> preprocessedFrames = preprocFrames(buf);
//has length of 20 -> no problem there (shouldn't affect dimensionality either...)
int[] output = new int[2];
float[][][] inputMatrices = new float[preprocessedFrames.toArray().length][320][240];
for(int i = 0; i < preprocessedFrames.toArray().length; i++) {
Mat inpRaw = preprocessedFrames.get(i);
Bitmap data = Bitmap.createBitmap(inpRaw.cols(), inpRaw.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(inpRaw, data);
int[][] pixels = pixelsFromBitmap(data);
float[][] inputMatrix = inputMatrixFromIntPixels(pixels);
// returns float[][] with floats from 0 to 1
inputMatrices[i] = inputMatrix;
}
try{
detector.run(inputMatrices, output);
Debug("results: " + output.toString());
}
The model gives me an output of 2 neurons translating into 2 labels.
The model code is the following:
model = tf.keras.Sequential(name='detector')
model.add(tf.keras.layers.Conv3D(filters=(56), input_shape=(20, 320, 240, 1), strides=(2,2,2), kernel_size=(3,11,11), padding='same', activation="relu"))
model.add(tf.keras.layers.AveragePooling3D(pool_size=(1,4,4)))
model.add(tf.keras.layers.Conv3D(filters=(72), kernel_size=(4,7,7), strides=(1,2,2), padding='same'))
model.add(tf.keras.layers.Conv3D(filters=(81), kernel_size=(2,4,4), strides=(2,2,2), padding='same'))
model.add(tf.keras.layers.Conv3D(filters=(100), kernel_size=(1,2,2), strides=(3,2,2), padding='same'))
model.add(tf.keras.layers.Conv3D(filters=(128), kernel_size=(1,2,2), padding='same'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(768, activation='tanh', kernel_regularizer=tf.keras.regularizers.l2(0.011)))
model.add(tf.keras.layers.Dropout(rate=0.1))
model.add(tf.keras.layers.Dense(256, activation='sigmoid', kernel_regularizer=tf.keras.regularizers.l2(0.012)))
model.add(tf.keras.layers.Dense(2, activation='softmax'))
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.00001), loss=tf.keras.losses.CategoricalCrossentropy(),
metrics=['accuracy'])
EDIT: I printed out the first input tensor as follows:
int[] shape = detector.getInputTensor(0).shape();
for(int r = 0; r < shape.length; r++){
Log.d("********" + r, "*******: " + r + " : " + shape[r]);
}
With that I first get the output [1,20,320,240,1]and after that I only get [20,320,240]. I am really quite desperate now...
So, I figured it out by myself and it seems like I really only had to make the input 5 dimensional by putting the content into a first dimension and every single pixel into a fifth dimension. I don't know why, but I will accept that xD.
float[][] output = new float[1][2];
float[][][][][] inputMatrices = new float[1][preprocessedFrames.toArray().length][320][240][1];
for(int i = 0; i < preprocessedFrames.toArray().length; i++) {
Mat inpRaw = preprocessedFrames.get(i);
Bitmap data = Bitmap.createBitmap(inpRaw.cols(), inpRaw.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(inpRaw, data);
int[][] pixels = pixelsFromBitmap(data);
float[][] inputMatrix = inputMatrixFromIntPixels(pixels);
for (int j = 0; j < inputMatrix.length - 1; j++) {
for(int k = 0; k < inputMatrix[0].length - 1; k++) {
inputMatrices[0][i][k][j][0] = inputMatrix[j][k];
}
}
}

creating a digital filter in android

I'm trying to deal with ECG signal processing in android. I want to implement simple digital filters (lowpass, highpass)
I've got a transfer function:
here is what i've found:
wikipedia - lowpass filter - it looks quite easy here.
for i from 1 to n
y[i] := y[i-1] + α * (x[i] - y[i-1])
but there is nothing about transfer function which I want to use.
I also found the following matlab code
%% Low Pass Filter H(z) = (1 - 2z^(-6) + z^(-12)) / (1 - 2z^(-1) + z^(-2))
b = [1 0 0 0 0 0 -2 0 0 0 0 0 1];
a = [1 -2 1];
h_l = filter(b,a,[1 zeros(1,12)]);
ecg_l = conv (ecg ,h_l);
but there is no function like filter and conv in java (or I missed something).
Also I was looking on stackoverflow for an answer. But I didn't found anything about transfer function.
so can someone help me? I just want to move on with my project.
Given a time-domain recurrence equation (such as the one you quoted from wikipedia), the corresponding transfer function in the z-domain can relatively easily be obtained by using the following properties:
Where X(z) and Y(z) are the z-transforms of the time-domain input sequence x and output sequence y respectively.
Going the other way around, given a transfer function which can be expressed as a ratio of polynomials in z, such as:
the recurrence equation of the transfer function can be written as:
There are of course many different ways to implement such a recurrence equation, but a simple filter implementation following the Direct Form II would be along the line of:
// Implementation of an Infinite Impulse Response (IIR) filter
// with recurrence equation:
// y[n] = -\sum_{i=1}^M a_i y[n-i] + \sum_{i=0}^N b_i x[n-i]
public class IIRFilter {
public IIRFilter(float a_[], float b_[]) {
// initialize memory elements
int N = Math.max(a_.length, b_.length);
memory = new float[N-1];
for (int i = 0; i < memory.length; i++) {
memory[i] = 0.0f;
}
// copy filter coefficients
a = new float[N];
int i = 0;
for (; i < a_.length; i++) {
a[i] = a_[i];
}
for (; i < N; i++) {
a[i] = 0.0f;
}
b = new float[N];
i = 0;
for (; i < b_.length; i++) {
b[i] = b_[i];
}
for (; i < N; i++) {
b[i] = 0.0f;
}
}
// Filter samples from input buffer, and store result in output buffer.
// Implementation based on Direct Form II.
// Works similar to matlab's "output = filter(b,a,input)" command
public void process(float input[], float output[]) {
for (int i = 0; i < input.length; i++) {
float in = input[i];
float out = 0.0f;
for (int j = memory.length-1; j >= 0; j--) {
in -= a[j+1] * memory[j];
out += b[j+1] * memory[j];
}
out += b[0] * in;
output[i] = out;
// shift memory
for (int j = memory.length-1; j > 0; j--) {
memory[j] = memory[j - 1];
}
memory[0] = in;
}
}
private float[] a;
private float[] b;
private float[] memory;
}
which you could use to implement your specific transfer function like so:
float g = 1.0f/32.0f; // overall filter gain
float[] a = {1, -2, 1};
float[] b = {g, 0, 0, 0, 0, 0, -2*g, 0, 0, 0, 0, 0, g};
IIRFilter filter = new IIRFilter(a, b);
filter.process(input, output);
Note that you can alternatively also factorize the numerator and denominator into 2nd order polynomials and obtain a cascade of 2nd order filters (known as biquad filters).

OpenCV convert color per pixel

Hello i want to convert the color in image, i'm using per-pixel methods but it seems very slow
src.getPixels(pixels, 0, width, 0, 0, width, height);
// RGB values
int R;
for (int i = 0; i < pixels.length; i++) {
// Get RGB values as ints
// Set pixel color
pixels[i] = color;
}
// Set pixels
src.setPixels(pixels, 0, width, 0, 0, width, height);
my question, is there any way i can do it using openCV? change pixel to the color i want ?
I recommend this excellent article on how to access/modify an opencv image buffer. I recommend
"the efficient way":
int i,j;
uchar* p;
for( i = 0; i < nRows; ++i)
{
p = I.ptr<uchar>(i);
for ( j = 0; j < nCols; ++j)
{
p[j] = table[p[j]];
}
Or "the iterator-safe method":
MatIterator_<Vec3b> it, end;
for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
{
(*it)[0] = table[(*it)[0]];
(*it)[1] = table[(*it)[1]];
(*it)[2] = table[(*it)[2]];
}
For further optimizations, using cv::LUT() (where possible) can give huge speedups, but it is more intensive to design/code.
You can access Pixels by using:
img.at<Type>(y, x);
So to change an RGB Value you can use:
// read color
Vec3b intensity = img.at<Vec3b>(y, x);
// compute new color using intensity.val[0] etc. to access color values
// write new color
img.at<Vec3b>(y, x) = intensity;
#Boyko mentioned an Article from OpenCV concerning fast access to the image pixels if you want to iterate over all Pixel. The Method I would prefer from this Article is the iterator Method, as it is only slightly slower than direct pointer access but safer to use.
Example Code:
Mat& AssignNewColors(Mat& img)
{
// accept only char type matrices
CV_Assert(img.depth() != sizeof(uchar));
const int channels = img.channels();
switch(channels)
{
// case 1: skipped here
case 3:
{
// Read RGG Pixels
Mat_<Vec3b> _img = img;
for( int i = 0; i < img.rows; ++i)
for( int j = 0; j < img.cols; ++j )
{
_img(i,j)[0] = computeNewColor(_img(i,j)[0]);
_img(i,j)[1] = computeNewColor(_img(i,j)[1]);
_img(i,j)[2] = computeNewColor(_img(i,j)[2]);
}
img = _img;
break;
}
}
return img;
}

CCPointFromString is crashing :( in cocos2dx 2.0.4

I am doing a CCPointFromString conversion but my coding crashing whenever I am trying to take input, Here is the code , what I am doing wrong?
CCPoint *temp = new CCPoint(oldLocationCon.x, oldLocationCon.y);
pointInsert->addObject(temp);
for(int i=0; i<pointInsert->count(); i++){
CCString point = (CCString*)pointInsert->objectAtIndex(i);
CCPoint savePoint= CCPointFromString(point->getCString());
}
CCArray * pointInsert = CCArray::create();
CCPoint * temp = new CCPoint(0, 0);
pointInsert->addObject(temp);
for(int i = 0; i < pointInsert->count(); i++){
CCString * point = static_cast<CCString*>(pointInsert->objectAtIndex(i));
CCPoint savePoint= CCPointFromString(point->getCString());
}

Code optimization for Opencv Android

I'm using this opencv code on Android for an intensity equalization. The time of execution is around 300ms per frame (720x480). Does anybody have an idea for a possible time optimization ?
Here is the code :
cvtColor(image, hsvImage, CV_BGR2HSV);
// Get intensity
intensity = hsvImage.at<Vec3b>((int)reference.Point_::y, (int)reference.Point_::x);
float value = (float)REGULAR_INTENSITY / intensity[2];
float saturation = (float)REGULAR_SATURATION / intensity[1];
if (counter == 15 && (int)intensity[2] < REGULAR_INTENSITY) {
equalization = false;
}
// Modify intensity
float transformedSaturation, transformedValue;
for(int i = 0; i < hsvImage.rows; i++) {
unsigned char *data = hsvImage.ptr(i);
for(int j = 0; j < hsvImage.cols; j++) {
transformedSaturation = (uchar)*++data * saturation;
if (transformedSaturation > MAX_COLOR) {
transformedSaturation = MAX_COLOR;
}
*data++ = transformedSaturation;
transformedValue = (uchar)*data * value;
if (transformedValue > MAX_COLOR) {
transformedValue = MAX_COLOR;
}
*data++ = transformedValue;
}
}
cvtColor(hsvImage, image, CV_HSV2BGR);
Have you tried using OpenCV transform ? I guess it is optimised, but I dont know about the saturating cast (that is if > max_color, then = max color)

Categories

Resources