Convert from org.bytedeco.javacv.Frame to matlab image - java

I am using this code in MATLAB R2015a:
javaaddpath('javacv.jar');
import org.bytedeco.javacv.*;
grabber = FrameGrabber.createDefault(0);
grabber.start();
img = grabber.grab();
And I got img variable that is org.bytedeco.javacv.Frame class.
How I convert this class to matlab image?
EDIT
I have half way through:
I Convert from org.bytedeco.javacv.Frame to org.bytedeco.javacpp.opencv_core$Mat
in this code:
javaaddpath('javacv.jar');
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.opencv_highgui.*;
grabber = FrameGrabber.createDefault(0);
grabber.start();
img = grabber.grab();
buff = img.image(1);
bytePointer = BytePointer(buff);
cvImage = javaObject('org.bytedeco.javacpp.opencv_core$Mat',img.imageHeight,img.imageWidth,opencv_core.CV_8UC3);
cvImage = cvImage.data(bytePointer);
imshow('tal',cvImage);
I can able to see correctly the image from imshow function.
Still I want to convert from org.bytedeco.javacpp.opencv_core$Ma to matlab image.
How I can do it?
Able to convert it in inefficient way,
Put the code here, hopefully someone will convert it to efficient way code,
and publish here as an answer.
javaaddpath('javacv.jar');
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
grabber = FrameGrabber.createDefault(0)
grabber.start();
img = grabber.grab();
buff = img.image(1);
w = img.imageWidth;
h = img.imageHeight;
%// from here is inefficient code
charBuff = buff.asCharBuffer;
n = charBuff.length;
data = repmat(uint16(0),n,1);
for i=0:n-1
data(i+1) = charBuff.get(i);
end
I = typecast(data, 'uint8');
I = cat(3, ...
reshape(I(3:3:end),[w h])', ...
reshape(I(2:3:end),[w h])', ...
reshape(I(1:3:end),[w h])' ...
);
imshow(I);
Faster way, still inefficient.
I think there is no more efficient way to do it, unless you write your own java code, that give you that byte array, because matlab give only duplicate of primitive array on function call, and not the array it self. the function can modified the array, but matlab do not duplicate the output when it done.
Read the "before last" comment in Problem on defining Java int array in Matlab
javaaddpath('javacv.jar');
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
grabber = FrameGrabber.createDefault(0)
grabber.start();
img = grabber.grab();
buff = img.image(1);
w = img.imageWidth;
h = img.imageHeight;
%// from here is inefficient code
doubleBuff = buff.asDoubleBuffer;
n = doubleBuff.remaining;
data = zeros(n,1);
for i=1:n
data(i) = doubleBuff.get();
end
I = typecast(data, 'uint8');
I = cat(3, ...
reshape(I(3:3:end),[w h])', ...
reshape(I(2:3:end),[w h])', ...
reshape(I(1:3:end),[w h])' ...
);
imshow(I);

Faster way, still inefficient.
I think there is no more efficient way to do it, unless you write your own java code, that give you that byte array, because matlab give only duplicate of primitive array on function call, and not the array it self. the function can modified the array, but matlab do not duplicate the output when it done.
Read the "before last" comment in Problem on defining Java int array in Matlab
javaaddpath('javacv.jar');
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
grabber = FrameGrabber.createDefault(0)
grabber.start();
img = grabber.grab();
buff = img.image(1);
w = img.imageWidth;
h = img.imageHeight;
%// from here is inefficient code
doubleBuff = buff.asDoubleBuffer;
n = doubleBuff.remaining;
data = zeros(n,1);
for i=1:n
data(i) = doubleBuff.get();
end
I = typecast(data, 'uint8');
I = cat(3, ...
reshape(I(3:3:end),[w h])', ...
reshape(I(2:3:end),[w h])', ...
reshape(I(1:3:end),[w h])' ...
);
imshow(I);

Related

Writing ".shape" equivalent in Java

I am rewriting Python code into Java code (Android) and I don't know how to perform the function .shape on an image.
Python:
def getProcessedImage(srcImage):
image = copy.copy(srcImage)
print ("image.shape"), image.shape
r = 600.0 / image.shape[1]
dim = (600, int(image.shape[0] * r))
print ("dimension ="), dim
Java:
public Mat getProcessedImage(srcImage) {
Mat image = new Mat(srcImage);
srcImage.copyTo(image);
Object[] truple = new Object[Array.getLength(srcImage)] //Got stuck here and don't even think its correct
// Mat processedImage =.......
return processedImage;
}
The equivalent in java to shape in python is srcImage.size().width and srcImage.size().height.

Reading Binary Picture Data from exiftool?

I'm working on a .opus music library software which converts audio/video files to .opus files and tags them with metadata automatically.
Previous versions of the program have saved the album art as binary data apparently as revealed by exiftool.
The thing is that when I run the command to output data as binary using the -b option, the entire thing is in binary seemingly. I'm not sure how to get the program to parse it. I was kind of expecting an entry like Picture : 11010010101101101011....
The output looks similar to this though:
How can I parse the picture data so I can reconstruct the image for newer versions of the program? (I'm using Java8_171 on Kubuntu 18.04)
It looks like you're trying to open the raw bytes in a text editor, which will of course give you gobble-dee-gook since those raw bytes do not represent characters that can be displayed by any text editor. I can see from your output from exiftool that you are able to know the length of the image in bytes. Providing you know the beginning byte position in the file, this should make your task relatively easy with a little bit of Java code. If you can get the starting position of the image inside your file, you should be able to do something like:
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
public class SaveImage {
public static void main(String[] args) throws IOException {
byte[] imageBytes;
try (RandomAccessFile binaryReader =
new RandomAccessFile("your-file.xxx", "r")) {
int dataLength = 0; // Assign this the byte length shown in your
// post instead of zero
int startPos = 0; // I assume you can find this somehow.
// If it's not at the beginning
// change it accordingly.
imageBytes = new byte[dataLength];
binaryReader.read(imageBytes, startPos, dataLength);
}
try (InputStream in = new ByteArrayInputStream(imageBytes)) {
BufferedImage bImageFromConvert = ImageIO.read(in);
ImageIO.write(bImageFromConvert,
"jpg", // or whatever file format is appropriate
new File("/path/to/your/file.jpg"));
}
}
}

Enlarging image using GD results in dismal quality compared to Scalr (JAVA)

I have been dealing with very small images and I have tried to discover the best way to increase them. I compared two different sources: imagecopyresampled (PHP: http://www.php.net/manual/en/function.imagecopyresampled.php) versus Scalr (JAVA: How to resize images in a directory?). I am including the codes that I am using below for the sake of completeness, but they are strongly based on other threads or sites referenced above. If someone thinks that I should remove, I will do that! In both sources it seems that the algorithm used to deal with the issue seems to be the same: Bicubic interpolation. However, in the case of the JAVA source, the quality of the resized image is MUCH MUCH better in my implementation (it is not even possible to compare). Am I doing something wrong when I am using the PHP source? If not, does anyone can explain me the difference between them?
JavaCode:
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import static org.imgscalr.Scalr.*;
public class App2 {
public static void main(String[] args) throws IOException {
for (File sourceImageFile : new File("imgs").listFiles()) {
if (sourceImageFile.getName().endsWith(".jpg"))
res(sourceImageFile.getAbsolutePath());
}
}
public static void res(String arg) throws IOException {
File sourceImageFile = new File(arg);
BufferedImage img = ImageIO.read(sourceImageFile);
BufferedImage thumbnail = resize(img, 500);
thumbnail.createGraphics().drawImage(thumbnail, 0, 0, null);
ImageIO.write(thumbnail, "jpg", new File("resized/" + sourceImageFile.getName()));
}
}
PHP code:
<?php
// The file
$filename = 'photos/thePhoto.jpg';
// Set a maximum height and width
$width = 250;
$height = 250;
// Content type
header('Content-Type: image/jpeg');
// Get new dimensions
list($width_orig, $height_orig) = getimagesize($filename);
$ratio_orig = $width_orig/$height_orig;
if ($width/$height > $ratio_orig) {
$width = $height*$ratio_orig;
} else {
$height = $width/$ratio_orig;
}
// Resample
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);
// Output
imagejpeg($image_p, null, 100);
?>
Just to be clear, in the JAVA code, I have to keep the images in a folder. In the PHP code, I provide the name of the file. Off course, I compared exactly the same image. Furthermore, both codes are running without any kind of problem.
![PHP versus Java (in this order)]: http://www.facebook.com/media/set/?set=a.122440714606196.1073741825.100005208033163&type=1&l=55d93c4969

How to print out the predicted class after cross-validation in WEKA

Once a 10-fold cross-validation is done with a classifier, how can I print out the prediced class of every instance and the distribution of these instances?
J48 j48 = new J48();
Evaluation eval = new Evaluation(newData);
eval.crossValidateModel(j48, newData, 10, new Random(1));
When I tried something similar to below, it said that the classifier is not built.
for (int i=0; i<data.numInstances(); i++){
System.out.println(j48.distributionForInstance(newData.instance(i)));
}
What I'm trying to do is the same function as in the WEKA GUI wherein once a classifier is trained, I can click on Visualize classifier error" > Save, and I will find the predicted class in the file. But now I need it in to work in my own Java code.
I have tried something like below:
J48 j48 = new J48();
Evaluation eval = new Evaluation(newData);
StringBuffer forPredictionsPrinting = new StringBuffer();
weka.core.Range attsToOutput = null;
Boolean outputDistribution = new Boolean(true);
eval.crossValidateModel(j48, newData, 10, new Random(1), forPredictionsPrinting, attsToOutput, outputDistribution);
Yet it prompts me the error:
Exception in thread "main" java.lang.ClassCastException: java.lang.StringBuffer cannot be cast to weka.classifiers.evaluation.output.prediction.AbstractOutput
The crossValidateModel() method can take a forPredictionsPrinting varargs parameter that is a weka.classifiers.evaluation.output.prediction.AbstractOutput instance.
The important part of that is a StringBuffer to hold a string representation of all the predictions. The following code is in untested JRuby, but you should be able to convert it for your needs.
j48 = j48.new
eval = Evalution.new(newData)
predictions = java.lange.StringBuffer.new
eval.crossValidateModel(j48, newData, 10, Random.new(1), predictions, Range.new('1'), true)
# variable predictions now hold a string of all the individual predictions
I was stuck some days ago. I wanted to to evaluate a Weka classifier in matlab using a matrix instead of loading from an arff file. I use http://www.mathworks.com/matlabcentral/fileexchange/21204-matlab-weka-interface and the following source code. I hope this help someone else.
import weka.classifiers.*;
import java.util.*
wekaClassifier = javaObject('weka.classifiers.trees.J48');
wekaClassifier.buildClassifier(processed);%Loaded from loadARFF
e = javaObject('weka.classifiers.Evaluation',processed);%Loaded from loadARFF
myrand = Random(1);
plainText = javaObject('weka.classifiers.evaluation.output.prediction.PlainText');
buffer = javaObject('java.lang.StringBuffer');
plainText.setBuffer(buffer)
bool = javaObject('java.lang.Boolean',true);
range = javaObject('weka.core.Range','1');
array = javaArray('java.lang.Object',3);
array(1) = plainText;
array(2) = range;
array(3) = bool;
e.crossValidateModel(wekaClassifier,testing,10,myrand,array)
e.toClassDetailsString
Asdrúbal López-Chau
clc
clear
%Load from disk
fileDataset = 'cm1.arff';
myPath = 'C:\Users\Asdrubal\Google Drive\Respaldo\DoctoradoALCPC\Doctorado ALC PC\AlcMobile\AvTh\MyPapers\Papers2014\UnderOverSampling\data\Skewed\datasetsKeel\';
javaaddpath('C:\Users\Asdrubal\Google Drive\Respaldo\DoctoradoALCPC\Doctorado ALC PC\AlcMobile\JarsForExperiments\weka.jar');
wekaOBJ = loadARFF([myPath fileDataset]);
%Transform from data into Matlab
[data, featureNames, targetNDX, stringVals, relationName] = ...
weka2matlab(wekaOBJ,'[]');
%Create testing and training sets in matlab format (this can be improved)
[tam, dim] = size(data);
idx = randperm(tam);
testIdx = idx(1 : tam*0.3);
trainIdx = idx(tam*0.3 + 1:end);
trainSet = data(trainIdx,:);
testSet = data(testIdx,:);
%Trasnform the training and the testing sets into the Weka format
testingWeka = matlab2weka('testing', featureNames, testSet);
trainingWeka = matlab2weka('training', featureNames, trainSet);
%Now evaluate classifier
import weka.classifiers.*;
import java.util.*
wekaClassifier = javaObject('weka.classifiers.trees.J48');
wekaClassifier.buildClassifier(trainingWeka);
e = javaObject('weka.classifiers.Evaluation',trainingWeka);
myrand = Random(1);
plainText = javaObject('weka.classifiers.evaluation.output.prediction.PlainText');
buffer = javaObject('java.lang.StringBuffer');
plainText.setBuffer(buffer)
bool = javaObject('java.lang.Boolean',true);
range = javaObject('weka.core.Range','1');
array = javaArray('java.lang.Object',3);
array(1) = plainText;
array(2) = range;
array(3) = bool;
e.crossValidateModel(wekaClassifier,testingWeka,10,myrand,array)%U
e.toClassDetailsString

How to use JCUDA to call CUBIN? [duplicate]

I said in this question that I had some problem loading ptx modules in JCuda and after #talonmies's idea, I implemented a JCuda version of his solution to load multiple ptx files and load them as a single module. Here is the related part of the code:
import static jcuda.driver.JCudaDriver.cuLinkAddFile;
import static jcuda.driver.JCudaDriver.cuLinkComplete;
import static jcuda.driver.JCudaDriver.cuLinkCreate;
import static jcuda.driver.JCudaDriver.cuLinkDestroy;
import static jcuda.driver.JCudaDriver.cuModuleGetFunction;
import static jcuda.driver.JCudaDriver.cuModuleLoadData;
import jcuda.driver.CUjitInputType;
import jcuda.driver.JITOptions;
import jcuda.driver.CUlinkState;
import jcuda.driver.CUfunction;
public class JCudaTestJIT{
private CUmodule module;
private CUfunction functionKernel;
public void prepareModule(){
String ptxFileName4 = "file4.ptx";
String ptxFileName3 = "file3.ptx";
String ptxFileName2 = "file2.ptx";
String ptxFileName1 = "file1.ptx";
CUlinkState linkState = new CUlinkState();
JITOptions jitOptions = new JITOptions();
cuLinkCreate(jitOptions, linkState);
cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName4, jitOptions);
cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName3, jitOptions);
cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName2, jitOptions);
cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName1, jitOptions);
long sizeOut = 32768;
byte[] image = new byte[32768];
Pointer cubinOut = Pointer.to(image);
cuLinkComplete(linkState, cubinOut, (new long[]{sizeOut}));
module = new CUmodule();
// Load the module from the image buffer
cuModuleLoadData(module, cubinOut.getByteBuffer(0, 32768).array());
cuLinkDestroy(linkState);
functionKernel = new CUfunction();
cuModuleGetFunction(functionKernel, module, "kernel");
}
// Other methods
}
But I got the error of CUDA_ERROR_INVALID_IMAGE at calling cuModuleLoadData method. While debugging it, I saw that after calling cuLinkComplete method and pass the image array as the output, the array is still unchanged and clear. Am I passing the output parameter correctly? Is this how one can pass a variable by reference in JCuda?
I had never written a single line of Java code until 30 minutes ago, let alone used JCUDA before, but an almost literal line-by-line translation of the native C++ code I gave you here seems to work perfectly:
import static jcuda.driver.JCudaDriver.*;
import java.io.*;
import jcuda.*;
import jcuda.driver.*;
public class JCudaRuntimeTest
{
public static void main(String args[])
{
JCudaDriver.setExceptionsEnabled(true);
cuInit(0);
CUdevice device = new CUdevice();
cuDeviceGet(device, 0);
CUcontext context = new CUcontext();
cuCtxCreate(context, 0, device);
CUlinkState linkState = new CUlinkState();
JITOptions jitOptions = new JITOptions();
cuLinkCreate(jitOptions, linkState);
String ptxFileName2 = "test_function.ptx";
String ptxFileName1 = "test_kernel.ptx";
cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName2, jitOptions);
cuLinkAddFile(linkState, CUjitInputType.CU_JIT_INPUT_PTX, ptxFileName1, jitOptions);
long sz[] = new long[1];
Pointer image = new Pointer();
cuLinkComplete(linkState, image, sz);
System.out.println("Pointer: " + image);
System.out.println("CUBIN size: " + sz[0]);
CUmodule module = new CUmodule();
cuModuleLoadDataEx(module, image, 0, new int[0], Pointer.to(new int[0]));
cuLinkDestroy(linkState);
CUfunction functionKernel = new CUfunction();
String kernelname = "_Z6kernelPfS_S_S_";
cuModuleGetFunction(functionKernel, module, kernelname);
System.out.println("Function: " + functionKernel);
}
}
which works like this:
> nvcc -ptx -arch=sm_21 test_function.cu
test_function.cu
> nvcc -ptx -arch=sm_21 test_kernel.cu
test_kernel.cu
> javac -cp ".;jcuda-0.7.0a.jar" JCudaRuntimeTest.java
> java -cp ".;jcuda-0.7.0a.jar" JCudaRuntimeTest
Pointer: Pointer[nativePointer=0xa5a13a8,byteOffset=0]
CUBIN size: 5924
Function: CUfunction[nativePointer=0xa588160]
The key here seems to be to use cuModuleLoadDataEx, noting that the return values from cuLinkComplete are a system pointer to the linked CUBIN and the size of the image returned as a long[]. As per the C++ code, the pointer is just passed directly to the module data load.
As a final comment, it would have been much simpler and easier if you had posted a proper repro case that could be been directly hacked on, rather than making me learn the rudiments of JCUDA and Java before I could create a useful repro case and get it to work. The documentation for JCUDA is basic, but complete, and against the working C++ example already provided, it only took a couple of minutes of reading to see how to do this.

Categories

Resources