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];
}
}
}
I am trying to build a card based game in which a card is added to player after every round. To win the match player has to remove all cards from his deck.However i have also drawn some additional button for some other purposes. The issue is that when the number of cards got high, they hide behind the buttons like below image.
Is there any way through which i can draw the bitmaps in a fixed area? Something like below image(Highlighted rectangle behind the card images).
Following is my code to draw Bitmaps for one player
private void setMainPlayer() {
// Log.d(TAG, "Inside Set Main Player Method");
Card localcard = null;
Bitmap localimage = null;
int currentiteration = 0;
int Card_Gap = Screen_Width / 10;
int Down_Card_Gap = 0;
int Down_Card_Gap_positive = 0;
int Down_Card_Gap_negative = 0;
playerList.get(0).sortBySuit();
// Log.d(TAG,"Main Player Deck size"+MainPlayer.Count());
while (currentiteration < playerList.get(0).decksize()) {
localcard = playerList.get(0).getCard(currentiteration);
localcard.setCurrent_Y(Screen_Height - localcard.getImage(context, Card_Width, Card_Height).getHeight());
playerList.get(0).setCurrentCard(localcard, currentiteration);
currentiteration++;
if (Down_Card_Gap >= 0) {
Down_Card_Gap_positive = Down_Card_Gap;
localcard.setCurrent_X(Screen_Center_X + Down_Card_Gap_positive);
Down_Card_Gap += Card_Gap;
} else {
Down_Card_Gap_negative = Down_Card_Gap;
localcard.setCurrent_X(Screen_Center_X + Down_Card_Gap_negative);
}
Down_Card_Gap *= -1;
}
}
private void DrawMainPlayerDeck(Canvas canvas) {
// Log.d(TAG, " Inside Draw Main Player Deck");
Card localcard;
int currentiteration = 0;
while (currentiteration < playerList.get(0).decksize()) {
localcard = playerList.get(0).getCard(currentiteration);
canvas.drawBitmap(localcard.getImage(context, Card_Width, Card_Height), localcard.getCurrent_X(), localcard.getCurrent_Y(), null);
currentiteration++;
}
}
I am drawing bitmaps on surfaceview.
Any suggestion would be really helpful.
Thanks in advance.
game.batch.begin();
for (Array obstacle_array123: obstacle_array) {
body = obstacle_array123;
for (Body bodies: body) {
if (bodies.getUserData() instanceof Array && bodies.isActive()) {
sprites_array = (Array)bodies.getUserData();
for (int fix_pos = 0; fix_pos < sprites_array.size; fix_pos++) {
sprite = sprites_array.get(fix_pos);
if (verts.size != 0) verts.removeRange(0, verts.size - 1);
f = bodies.getFixtureList().get(fix_pos);
s = (PolygonShape)f.getShape();
transform = bodies.getTransform();
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(new Vector2(tmp));
}
rotation_point.set((verts.get(0).x + verts.get(1).x + verts.get(2).x + verts.get(3).x) / 4, (verts.get(0).y + verts.get(1).y + verts.get(2).y + verts.get(3).y) / 4);
sprite.setPosition(rotation_point.x - sprite.getWidth() / 2, rotation_point.y - sprite.getHeight() / 2);
sprite.setRotation(bodies.getAngle() * MathUtils.radiansToDegrees);
sprite.draw(game.batch);
}
}
}
}
game.batch.end();
I have a game where my bodies are made from multiple square fixtures, so this is the code to render each square sprite on each square fixture.
2 problems - 1.st --> it only renders the first sprite in the array
2.nd --> if you look at the following loop (SOLVED)
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(new Vector2(tmp));
}
well it is apperantly different compared to
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(tmp);
}
The spawned coordinates in 2nd example are wrong for half width and half height of the square.
When I try to get the coordinated from both examples the numbers are the same, but when setting the sprite position, 2nd example goes off.
You should probably ask both questions separately, but to answer your second question, then they ARE different.
In the first one you add a new Vector2 to verts each time through the loop. So verts will end up holding a load of different Vector2's.
In the second one you add the same Vector2 to verts over and over again, so it will just have one Vector2 with the same value over and over again (remember Java is pass by reference).
Caveat - My answer assumes that verts is some sort of standard collection or a libgdx Array.
I created 5 sprites using libgdx library, then want to assign the different size to all of them between 0 to 10 and then move from left to right. 5 sprite is succussfully created but the problem is in the size. i tried the S.nextInt(10). but its not working.
Also i want to create all the sprites between 100-200 height. how to do it?
int number = 5;
sprite = new Sprite[number];
for (int i = 0; i < number; i++) {
sprite[i] = new Sprite(texture);
int size = S.nextInt(10);
sprite[i].setSize(size, size);
speed = S.nextInt(2);
sprite[i].setPosition(speed, 100);
}
batch.begin();
for (int i = 0; i < number; i++) {
sprite[i].draw(batch);
}
batch.end();
I am working to convert my CCScrollLayer.cpp code into more of a CCPicker code. In CCScrollLayer, I've defined a baselayer (CCColorLayer) to hold all of the menu objects. I also have a border that holds the ScrollLayer (using glScissor) called "overlay" that I want to be completely static.
In Objective C:
...
self.baseLayer = [CCLayerColor layerWithColor:(ccColor4B){150,150,150,0} width:s.width height:imgSize.height * numPages];
for (int i=0; i < [arrayPages count]; i++) {
CCNode* n = arrayPages[i];
n.position = ccp(s.width/2, s.height/2 + i * (imgSize.height + padding));
[baselayer addChild:n];
}
baseLayer.position = ccp(-s.width/2, -s.height/2 - s.height * currentPage);
[self addChild:baselayer];
...
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint n = [self convertTouchToNodeSpace:touch];
baselayer.position = ccp(touchStartedbaseLayerPosition.x, touchStartedbaseLayerPosition.y + n.y - touchStartedPoint.y);
}
In C++
...
overlay=new CCSprite();
overlay->initWithFile("overlay.png");
overlay->setPosition(ccp(300,300));
overlay->autorelease();
CCLayerColor* baselayer = new CCLayerColor();
baselayer->initWithColor(ccc4(255, 255, 255,255));
baselayer->setOpacity(255);
baselayer->setContentSize(CCSizeMake(s.width/10, (layers->count()*scrollWidth)));
baselayer->setPosition(s.width*.41,300);
baselayer->autorelease();
// Loop through the array and add the screens
unsigned int i;
for (i=0; i<layers->count(); i++)
{
CCLayer* l = static_cast<CCLayer*>(layers->objectAtIndex(i));
l->setAnchorPoint(ccp(0,0));
l->setPosition(ccp(s.width/40,(i*scrollWidth)));
baselayer->addChild(l);
}
this->addChild(baselayer,1);
this->addChild(overlay,1);
...
void CCScrollLayer::ccTouchMoved(CCTouch *touch, CCEvent *withEvent)
{
CCPoint touchPoint = touch->getLocation(); // Get the touch position
touchPoint = this->getParent()->convertToNodeSpace(touchPoint);
baselayer->setPosition(ccp(0,(-(currentScreen-1)*scrollWidth)+(touchPoint.y-startSwipe)));
}
I'm not sure what I'm doing wrong, but as soon as I try to start scrolling, I get a fatal error in the touchdispatcher
case CCTOUCHMOVED:
pHandler->getDelegate()->ccTouchMoved(pTouch, pEvent);
I'm guessing I'm missing something simple here. Can you point me in the write direction?