I am trying to convert an open cv mat of type CV_8UC3 (RGB) to an integer array.
void copyMatToJIntArray(Mat m,jint* jia)
{
Mat tempMat;
cvtColor(m,tempMat,CV_BGRA2RGB);
jint size = tempMat.rows*tempMat.cols* tempMat.elemSize();
u_char * uchars = new u_char[size];
for(int r=0;r<tempMat.rows;r++)
{
for(int c=0;c<tempMat.cols;c++)
{
u_char r=*(tempMat.data+ r*tempMat.step + c);
u_char g=*(tempMat.data+ r*tempMat.step + c+1);
u_char b=*(tempMat.data+ r*tempMat.step + c+2);
uchars[r*tempMat.step+c]=r;
uchars[r*tempMat.step+c+1]=g;
uchars[r*tempMat.step+c+2]=b;
}
}
for (int i = 0; i < tempMat.rows*tempMat.cols; i++)
{
jia[i] = uchars[i];
}
}
I pass this inteher array via JNI to android java where it is converted into an a bitmap
croppedImageBitmap.setPixels(BGRA, 0, width, 0, 0, width, height);
imageView1.setImageBitmap(croppedImageBitmap);
But when I view it on my android test phone, there is a blue tint over the image
I don't know Java but it is almost the same as opencv in c++, you can use my c++ version:
typedef std::vector<std::vector<int> > Matrix;
Matrix int_Im(3, std::vector<int>(m.cols*m.rows,0));
Matrix copyMatToJIntArray(Mat m,jint* jia)
{
for(auto j=0, k = 0;j<m.rows;j++)
for(auto i=0;i<m.cols;i++)
{
int_Im[k][0] = m.at<uchar>(j,i)[0];
int_Im[k][1] = m.at<uchar>(j,i)[1];
int_Im[k][2] = m.at<uchar>(j,i)[2];
k++;
}
return int_Im;
}
Try this
jintArray resultImage = env->NewIntArray(h.total());
jint *_data = new jint[h.total()];
for (int i = 0; i < h.total(); i++) {
char b = h.data[h.channels() * i];
char g = h.data[h.channels() * i + 1];
char r = h.data[h.channels() * i + 2];
char a = 255;
_data[i] = (((jint) a << 24) & 0xFF000000) + (((jint) r << 16) & 0x00FF0000) +
(((jint) g << 8) & 0x0000FF00) + ((jint) b & 0x000000FF);
}
env->SetIntArrayRegion(resultImage, 0, h.total(), _data);
delete[]_data;
And on your java side
int[] result = yourfunction();
Bitmap bitmap = Bitmap.createBitmap(result, yourimagewidth, yourimageheight, Bitmap.Config.ARGB_8888);
Array data format should correspond to the Mat's type according to this table
public static Mat arrayToMat(double[][] array,int height, int width, int matType)
{
Mat image = new Mat(height,width,matType);
for (int i=0; i<height; i++)
{
for (int j=0; j<width; j++)
{
image.put(i,j,array[i][j]);
}
}
return image;
}
public static double[][] matToArray(Mat frame)
{
double array[][] = new double[frame.height()][frame.width()];
for (int i=0; i < frame.height(); i++)
{
for (int j=0; j < frame.width(); j++)
{
array[i][j] = frame.get(i,j)[0];
}
}
return array;
}
Related
I wanna make a pixel image for every color, but this code only makes (255,255,255,255) images. It loops through the entire for loop before it uses the int values for the creation of the images. How do I stop it at each integer during the for loop so I can make images that start at (0,0,0,0) then go to (0,0,0,1) and then (0,0,0,2) and so on all the way to (255,255,255,255)? so, I need to make 4,294,967,296 images in total.
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException{
int width = 1;
int height = 1;
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
File f = null;
try{
for(int i = 0; i < 4294967297; i++) {
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++){
for(int alpha = 0; alpha < 256; alpha++){
for(int red = 0; red < 256; red++){
for(int green = 0; green < 256; green++){
for(int blue = 0; blue < 256; blue++) {
int a = alpha;
int r = red;
int g = green;
int b = blue;
int p = (a << 24) | (r << 16) | (g << 8) | b;
img.setRGB(x, y, p);
}
}
}
}
}
}
f = new File("/Users/dimensionalengineer/Downloads/Colors/Color" + i + ".png");
ImageIO.write(img, "png", f);
}
} catch(IOException e) {
System.out.println("Error: " + e);
}
}
}
If you change the order of the for loops it will create one image for each possible colors. But beware that your file manager might not be able to handle that many files inside of one directory.
BufferedImage img = null;
File f = null;
int width = 1;
int height = 1;
int i = 0;
// loop for every possible color
for(int alpha = 0; alpha < 256; alpha++){
for(int red = 0; red < 256; red++){
for(int green = 0; green < 256; green++){
for(int blue = 0; blue < 256; blue++) {
// create one image filled with one color
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int a = alpha;
int r = red;
int g = green;
int b = blue;
int p = (a << 24) | (r << 16) | (g << 8) | b;
// loop every pixel
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++){
img.setRGB(x, y, p);
}
}
// save to file
f = new File("/Users/dimensionalengineer/Downloads/Colors/Color" + i++ + ".png");
ImageIO.write(img, "png", f);
// free ram
img.dispose();
}
}
}
}
Good morning. I'm a developer trying to put a tensorflow model into Android.
I've encountered an error that I've never seen before while trying to fix it with multiple errors.
The java.nio.BufferOverFlowException error i'm facing now is that it didn't happen before, but it happened suddenly.
My code uses a byte array, but i cannot specify which part is the problem.
This source that takes a float array as input and returns an array with 10 classes after passing through the model.
The returned values have softmax value.
public float[] hypothesis(float[] inputFloats, int nFeatures, int nClasses, Context context)
{
try {
int nInstance = inputFloats.length / nFeatures;
// FloatBuffer.wrap(inputFloats);
Toast.makeText(context, "", Toast.LENGTH_LONG).show();
inferenceInterface.feed(INPUT_NODE, FloatBuffer.wrap(inputFloats), INPUT_SIZE);
inferenceInterface.run(OUTPUT_NODES_HYPO);
float[] result = new float[nInstance * nClasses];
inferenceInterface.fetch(OUTPUT_NODE_HYPO, result);
return result;
}
catch(Exception e){
Toast.makeText(context, e+" ...", Toast.LENGTH_LONG).show();
return null;
}
}
The length of the inputfloats is 720 and the nFeatures is 720. nClasses is 10.
Although the value is not correct, it worked before.
e in the catch statement prints java.nio.BufferOverFlowException.
Could there be a problem in the middle of converting a byte array to a float array?
Related source.
public float[] bytetofloat(byte[] array){
int[] returnArr = new int[array.length/4];
float[] returnArr1 = new float[array.length/4];
for(int i = 0 ; i < returnArr.length; i++){
//array[i] = 0;
returnArr[i] = array[i*4] & 0xFF;
if(returnArr[i] < 0 || returnArr[i]>255)
Log.d("ARRAY", returnArr[i]+" ");
returnArr1[i] = (float)returnArr[i];
}
return returnArr1;
}
public Bitmap RGB2GRAY(Bitmap image){
int width = image.getWidth();
int height = image.getHeight();
Bitmap bmOut;
bmOut = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
for(int x = 0; x < width; x++){
for(int y = 0 ; y < height; y++){
int pixel = image.getPixel(x, y);
int A = Color.alpha(pixel);
int R = Color.red(pixel);
int G = Color.green(pixel);
int B = Color.blue(pixel);
R = G = B = (int)(0.2126 * R + 0.7152 * G + 0.0722 * B);
bmOut.setPixel(x, y, Color.argb(A, R, G, B));
}
}
return bmOut;
}
private void activityPrediction(float[] inputArray){
try {
float[] result = activityInference.hypothesis(inputArray, 20*36, 10, getApplicationContext());
predictionView.setText(Arrays.toString(result));
}
catch (Exception e){
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private byte[] bitmapToByteArray(Bitmap bitmap)
{
int chunkNumbers = 10;
int bitmapSize = bitmap.getRowBytes() * bitmap.getHeight();
byte[] imageBytes = new byte[bitmapSize];
int rows, cols;
int chunkHeight, chunkWidth;
rows = cols = (int) Math.sqrt(chunkNumbers);
chunkHeight = bitmap.getHeight() / rows;
chunkWidth = bitmap.getWidth() / cols;
int yCoord = 0;
int bitmapsSizes = 0;
for (int x = 0; x < rows; x++)
{
int xCoord = 0;
for (int y = 0; y < cols; y++)
{
Bitmap bitmapChunk = Bitmap.createBitmap(bitmap, xCoord, yCoord, chunkWidth, chunkHeight);
byte[] bitmapArray = getBytesFromBitmapChunk(bitmapChunk);
System.arraycopy(bitmapArray, 0, imageBytes, bitmapsSizes, bitmapArray.length);
bitmapsSizes = bitmapsSizes + bitmapArray.length;
xCoord += chunkWidth;
bitmapChunk.recycle();
bitmapChunk = null;
}
yCoord += chunkHeight;
}
return imageBytes;
}
private byte[] getBytesFromBitmapChunk(Bitmap bitmap)
{
int bitmapSize = bitmap.getRowBytes() * bitmap.getHeight();
ByteBuffer byteBuffer = ByteBuffer.allocate(bitmapSize);
bitmap.copyPixelsToBuffer(byteBuffer);
byteBuffer.rewind();
return byteBuffer.array();
}
'e.printStackTrace()' result
at com.example.leehanbeen.platerecognize.ActivityInference.hypothesis(ActivityInference.java:58)
at com.example.leehanbeen.platerecognize.MainActivity.activityPrediction(MainActivity.java:148)
at com.example.leehanbeen.platerecognize.MainActivity.access$100(MainActivity.java:28)
at com.example.leehanbeen.platerecognize.MainActivity$2.onClick(MainActivity.java:69)
around MainActivity.java:69
byte[] byteArrayRes = bitmapToByteArray(image_bitmap);
float[] inputArray = bytetofloat(byteArrayRes);
activityPrediction(inputArray);
MainActivity.java:28
public class MainActivity extends AppCompatActivity {
MainActivity.java:148
float[] result = activityInference.hypothesis(inputArray, 20*36, 10, getApplicationContext());
around ActivityInference.java:58
float[] result = new float[nInstance * nClasses];
inferenceInterface.fetch(OUTPUT_NODE_HYPO, result);
I am trying to get a log transformation from a gray image. But with whatever c value I will get a black image. Any idea?
that is my method:
///---------------------------------------------------
public static BufferedImage log_trans (int[][] imageData , int c){
BufferedImage LogImage = new BufferedImage(imageData.length, imageData[0].length, BufferedImage.TYPE_BYTE_GRAY);
double temp;
for (int i =0 ; i<imageData.length ; i ++){
for (int j=0 ; j<imageData[0].length ; j++){
int rgb = imageData[i][j];
rgb = (rgb<<16)|(rgb<<8)|(rgb);
temp = Math.log10(rgb+1);
rgb = (int) (c * temp);
LogImage.setRGB(i, j, rgb);
}}
return LogImage;
}
--------------------------------------------------------------
public static int[][] readimage(File filename){
BufferedImage img;
try {
img = ImageIO.read(filename);
// Gray_scaled Image output
int width = img.getWidth();
int height = img.getHeight();
ImagePro.fw=width;
ImagePro.fh = height;
int [][] readimageVal = new int [width][height];
for (int i = 0; i<height ; i++){
for (int j =0 ; j<width ; j++){
Color c = new Color(img.getRGB(j, i));
int r= (int)(c.getRed() * 0.299)&0xff;
int g = (int)(c.getGreen() * 0.587)&0xff;
int b = (int)(c.getBlue() *0.114)&0xff;
int avg = ((r+b+g));
readimageVal[j][i] = avg;
}
}
return readimageVal;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
It seems that "rgb" is always negative, so temp is always Nan, so in the end "rgb" after:
rgb = (int) (c * temp);
is always 0 and this is why you always get black picture.
After changing your 8th line to:
rgb = (((byte)rgb & 0xFF)<<16)|(((byte)rgb & 0xFF)<<8)|(((byte)rgb & 0xFF));
I get some very dark output, but it's not very nice. I tested for value of "c" being 1, 18000, 180000 and 0x00FFFFFF.
i´m trying to convert a image into a matrix and convert it back, but the 2 pictures are different:
convert it into a matrix:
public int[][] getMatrixOfImage(BufferedImage bufferedImage) {
int width = bufferedImage.getWidth(null);
int height = bufferedImage.getHeight(null);
int[][] pixels = new int[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
pixels[i][j] = bufferedImage.getRGB(i, j);
}
}
return pixels;
}
and convert it back into a bufferedImage:
public BufferedImage matrixToBufferedImage(int[][] matrix) {
int width=matrix[0].length;
int height=matrix.length;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
int pixel=matrix[i][j] <<24|matrix[i][j] <<16|matrix[i][j]<<8|matrix[i][j] ;
bufferedImage.setRGB(i, j, pixel);
}
}
return bufferedImage;
}
with this result:
http://img59.imageshack.us/img59/5464/mt8a.png
Thanks!
Why do you do
int pixel=matrix[i][j] <<24|matrix[i][j] <<16|matrix[i][j]<<8|matrix[i][j];
instead of just
int pixel=matrix[i][j];
?
I'm creating an Image filter program and I want to convert a coloured picture to a grayscale picture with the help of an array matrix.
This is what I have currently:
import java.awt.Color;
import se.lth.cs.ptdc.images.ImageFilter;
public class GrayScaleFilter extends ImageFilter {
public GrayScaleFilter(String name){
super(name);
}
public Color[][] apply(Color[][] inPixels, double paramValue){
int height = inPixels.length;
int width = inPixels[0].length;
Color[][] outPixels = new Color[height][width];
for (int i = 0; i < 256; i++) {
grayLevels[i] = new Color(i, i, i);
}
for(int i = 0; i < height; i++){
for(int j = 0; j < width; j++){
Color pixel = inPixels[i][j];
outPixels[i][j] = grayLevels[index];
}
}
return outPixels;
}
}
It looks like I'm supposed to use this formula: ((R+G+B)/3)
I want to create an array matrix like this:
Color[] grayLevels = new Color[256];
// creates the color (0,0,0) and puts it in grayLevels[0],
// (1,1,1) in grayLevels[1], ..., (255,255,255) in grayLevels[255]
This is the class I'm refering too when I want to use grascale:
public abstract Color[][] apply(Color[][] inPixels, double paramValue);
protected short[][] computeIntensity(Color[][] pixels) {
int height = pixels.length;
int width = pixels[0].length;
short[][] intensity = new short[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
Color c = pixels[i][j];
intensity[i][j] = (short) ((c.getRed() + c.getGreen() + c
.getBlue()) / 3);
}
}
return intensity;
}
Any feedback on how I can achieve this? Instead of using outPixels[i][j] = new Color(intensity, intensity, intensity);
Build the grayLevels array this way:
for (int i = 0; i < 256; i++) {
grayLevels[i] = new Color(i, i, i);
}
Then, when you need a certain color, just retrieve it as grayLevels[index].