Showing posts with label Imageprocessing. Show all posts
Showing posts with label Imageprocessing. Show all posts

Tuesday, January 25, 2022

Install OpenCv in Linux/Ubuntu for Java Application.


1. Introduction:

In this blog post, we are going to install and set up OpenCV in ubuntu os for the java applications. OpenCV is a widely used great computer vision library. You can learn more about the OpenCV tutorial from here. For documentation, you can follow here. We will also cover some tutorials for Java bindings too.
 



2. Download OpenCV:

You can download OpenCV from the public Github repository of OpenCV or from their official website from here.  Select the desired version and click "Sources", which will download the zip file. Unzip the file.
unzip opencv-4.3.0.zip

 
3. Build OpenCV:

In order to build OpenCV, go to the OpenCV path in my case it's under "/opt/opencv-4.3.0" so I will use the same.

Create a directory to build.
mkdir build
  cd build
Now, if you don't have installed cmake software please install it using the below command
sudo apt-get  install cmake
Next, is to generate and configure with cmake for building executables in our system.
cmake -DBUILD_SHARED_LIBS=OFF ..
Note: When OpenCV is built as a set of static libraries (-DBUILD_SHARED_LIBS=OFF option) the Java bindings dynamic library is all-sufficient, i.e. doesn’t depend on other OpenCV libs, but includes all the OpenCV code inside. 

Make sure the output of the above command looks like below:


If it doesn't find the ant and java then you may get the following output: 
Java:
   ant:                         NO
   JNI:                         NO
   Java tests:                 YES
For this, install and setup your java and install ant
sudo apt install openjdk-8-jdk
sudo apt-get install ant

If you are still getting ant as NO then try the following command to install ant
sudo snap install ant --classic
Now start the build
make -j4
Note: Be careful not to run out of memory during the build. We need 4GB of memory per core. For example, if we compile with 4 cores (e.g. make -j4) we need a machine with at least 16GB of RAM.

The output look likes this and it will take some time.


If everything is fine, you successfully build OpenCV. Make sure the following files are packaged in the corresponding directory.
/opt/opencv-4.3.0/build/lib/libopencv_java430.so
/opt/opencv-4.3.0/build/bin/opencv-430.jar
The path of those files is created according to your OpenCV version and directory. You need to make sure the so and jar file must be created. This jar file contains the java wrapper code which we will used in the sample example.

 



4. Run Sample Example:

Now we are going to add the compiled jar file in our project library.

For IntelliJ Idea:

Go to : File >> Project Structure >> Libraries (under project settings)

you can see the + icon at the top left, to add a new project library click on it, and select java and add the path of previously created jar file i.e opencv-430.jar. 

It's time to run a sample test example.
import org.opencv.core.CvType;
import org.opencv.core.Mat;

public class SampleTest {

    public static void main(String[] args) {
        System.load("/opt/opencv-4.3.0/build/lib/libopencv_java430.so");
        Mat mat = Mat.eye(3, 3, CvType.CV_8UC1);
        System.out.println("mat = " + mat.dump());
    }
}
Make sure that you loaded your corresponding .so file.

Output:
mat = [  1,   0,   0;
   0,   1,   0;
   0,   0,   1]
For those who are running OpenCV in an existing project, you can set up with Gradle project as below:

For Gradle:

Copy the jar file in your project directory package for e.g "libs" and add following inside dependencies in build.gradle file.
dependencies {
//other dependencies

compile fileTree(dir: 'libs', include: '*.jar')
}
Share:

Monday, January 17, 2022

Read Dicom Image metadata using PixelMed in Java

In this tutorial, we are going to learn how to get Dicom image metadata using PixelMed toolkit using Java.

DICOM (Digital Imaging and Communications in Medicine) is the ubiquitous standard in the radiology and cardiology imaging industry for the exchange and management of images and image-related information.

DICOM is also used in other images related medical fields, such as pathology, endoscopy, dentistry, ophthalmology, and dermatology.

PixelMed Java DICOM Toolkit is a stand-alone DICOM toolkit that implements code for reading and creating DICOM data, DICOM network and file support, a database of DICOM objects, support for display of directories, images, reports, and spectra, and DICOM object validation.

The toolkit is an implementation, which does not depend on any other DICOM tools. This is the freely available pure Java tools for compression and XML and database support.

Download the .jar file from PixelMed Jar. Create a folder called libs inside the project directory and add the jar file and load it from the Ide.

Loading Jar file in Maven Project:

Add the following system dependency inside pom.xml file.

<dependency>
           <groupId>com.pixelmed</groupId>
           <artifactId>pixelmed</artifactId>
           <version>20220117</version>
           <scope>system</scope>
           <systemPath>${basedir}/libs/pixelmed.jar</systemPath>
       </dependency>

Note: use the downloaded jar file name.

Loading Jar in Gradle Project:

Add the following inside dependencies in build.gradle file.

dependencies {
//other dependencies
 
compile fileTree(dir: 'libs', include: '*.jar')
}

Now, let's create a sample java class called ReadMetaDataPixelMed.java and create the main method to execute the code.

    private static AttributeList attributeList = new AttributeList();
public static void main(String[] args) {
        String dcmFilePath = "/path_to_dicom_image/N2D_0001.dcm";
        try {
            readAttributes(dcmFilePath);
            Map<String, String> metaData = readMetadata();
            for (Map.Entry<String, String> entry :metaData.entrySet()) {
                System.out.println(entry.getKey()+" : "+entry.getValue());
            }
        }catch (Exception e) {
            System.out.println("Error due to: "+e.getMessage());
        }
    }

Create the methods used inside it.

private static void readAttributes(String dcmFilePath) throws DicomException, IOException {
        attributeList.read(new File(dcmFilePath));
    }

readAttributes method read the attributes or tag of the Dicom image. For Dicom library Tags and their description please visit Dicom Library.

 private static Map<String, String> readMetadata() throws DicomException {
        Map<String, String> metaData = new LinkedHashMap<>();
        metaData.put("Patient Name", getTagInformation(TagFromName.PatientName));
        metaData.put("Patient ID", getTagInformation(TagFromName.PatientID));
        metaData.put("Transfer Syntax", getTagInformation(TagFromName.TransferSyntaxUID));
        metaData.put("SOP Class", getTagInformation(TagFromName.SOPClassUID));
        metaData.put("Modality", getTagInformation(TagFromName.Modality));
        metaData.put("Samples Per Pixel", getTagInformation(TagFromName.SamplesPerPixel));
        metaData.put("Photometric Interpretation", getTagInformation(TagFromName.PhotometricInterpretation));
        metaData.put("Pixel Spacing", getTagInformation(TagFromName.PixelSpacing));
        metaData.put("Bits Allocated", getTagInformation(TagFromName.BitsAllocated));
        metaData.put("Bits Stored", getTagInformation(TagFromName.BitsStored));
        metaData.put("High Bit", getTagInformation(TagFromName.HighBit));
        SourceImage img = new com.pixelmed.display.SourceImage(attributeList);
        metaData.put("Number of frames", String.valueOf(img.getNumberOfFrames()));
        metaData.put("Width", String.valueOf(img.getWidth()));
        metaData.put("Height", String.valueOf(img.getHeight()));
        metaData.put("Is Grayscale", String.valueOf(img.isGrayscale()));
        metaData.put("Pixel Data present", String.valueOf(!getTagInformation(TagFromName.PixelData).isEmpty()));
        return metaData;
    }

Here, we are reading some sample metadata. For more metadata lists please visit TagFromName.java class and use the desired one.

private static String getTagInformation(AttributeTag tag) {
        return Attribute.getDelimitedStringValuesOrDefault(attributeList, tag, "NOT FOUND");
    }

If the attribute is found then this method returns the value of that attribute if not found then return NOT FOUND text.

Output:

Patient Name : Jane_Doe
Patient ID : 02
Transfer Syntax : 1.2.840.10008.1.2
SOP Class : 1.2.840.10008.5.1.4.1.1.4
Modality : MR
Samples Per Pixel : 1
Photometric Interpretation : MONOCHROME2
Pixel Spacing : 0.666666686534882\0.699987828731537
Bits Allocated : 16
Bits Stored : 16
High Bit : 15
Number of frames : 1
Width : 274
Height : 384
Is Grayscale : true
Pixel Data present : true

The overall code implementation looks like below:

package dicom;

import com.pixelmed.dicom.*;
import com.pixelmed.display.SourceImage;

import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

public class ReadMetaDataPixelMed {

    private static AttributeList attributeList = new AttributeList();

    public static void main(String[] args) {
        String dcmFilePath = "/path_to_dicom_image/N2D_0001.dcm";
        try {
            readAttributes(dcmFilePath);
            Map<String, String> metaData = readMetadata();
            for (Map.Entry<String, String> entry :metaData.entrySet()) {
                System.out.println(entry.getKey()+" : "+entry.getValue());
            }
        }catch (Exception e) {
            System.out.println("Error due to: "+e.getMessage());
        }
    }

    private static void readAttributes(String dcmFilePath) throws DicomException, IOException {
        attributeList.read(new File(dcmFilePath));
    }

    private static Map<String, String> readMetadata() throws DicomException {
        Map<String, String> metaData = new LinkedHashMap<>();
        metaData.put("Patient Name", getTagInformation(TagFromName.PatientName));
        metaData.put("Patient ID", getTagInformation(TagFromName.PatientID));
        metaData.put("Transfer Syntax", getTagInformation(TagFromName.TransferSyntaxUID));
        metaData.put("SOP Class", getTagInformation(TagFromName.SOPClassUID));
        metaData.put("Modality", getTagInformation(TagFromName.Modality));
        metaData.put("Samples Per Pixel", getTagInformation(TagFromName.SamplesPerPixel));
        metaData.put("Photometric Interpretation", getTagInformation(TagFromName.PhotometricInterpretation));
        metaData.put("Pixel Spacing", getTagInformation(TagFromName.PixelSpacing));
        metaData.put("Bits Allocated", getTagInformation(TagFromName.BitsAllocated));
        metaData.put("Bits Stored", getTagInformation(TagFromName.BitsStored));
        metaData.put("High Bit", getTagInformation(TagFromName.HighBit));
        SourceImage img = new com.pixelmed.display.SourceImage(attributeList);
        metaData.put("Number of frames", String.valueOf(img.getNumberOfFrames()));
        metaData.put("Width", String.valueOf(img.getWidth()));
        metaData.put("Height", String.valueOf(img.getHeight()));
        metaData.put("Is Grayscale", String.valueOf(img.isGrayscale()));
        metaData.put("Pixel Data present", String.valueOf(!getTagInformation(TagFromName.PixelData).isEmpty()));
        return metaData;
    }

    private static String getTagInformation(AttributeTag tag) {
        return Attribute.getDelimitedStringValuesOrDefault(attributeList, tag, "NOT FOUND");
    }
}
Share:

Friday, January 7, 2022

Install SimpleITK on Linux/Ubuntu for Java Application

In this tutorial, we are going to learn how to install SimpleITK which is very handy for medical image analysis.

SimpleITK is a simplified programming interface to the algorithms and data structures of the Insight Toolkit (ITK). It supports bindings for multiple programming languages including C++, Python, R, Java, C#, Lua, Ruby, and TCL. These bindings enable scientists to develop image analysis workflows in the programming language they are most familiar with. The toolkit supports more than 15 different image file formats, provides over 280 image analysis filters, and implements a unified interface to the ITK intensity-based registration framework. you can check out official documentation from here.

For the windows system, we can find the prebuilt library where we can simply download and install it. But for Linux os, we need to build by ourselves.

Installation:

Download SimpleItk: 

Clone the SimpleITK from the github.  We can select the desired version from release and download or clone it.


git clone https://github.com/SimpleITK/SimpleITK.git

Now change to the SimpleITK directory:

cd SimpleITK

Install Cmake:

sudo apt-get  install cmake
Install Java:
sudo apt install openjdk-8-jdk

Build SimpleITK

mkdir SimpleITK-build
cd SimpleITK-build
sudo cmake ../SuperBuild

The SuperBuild generates make files that take care of downloading and building ITK. Now start the build

make -j4

Note: Be careful not to run out of memory during the build. We need 4GB of memory per core. For example, if we compile with 4 cores (e.g. make -j4) we need a machine with at least 16GB of RAM.

It will take some time. After the installation, you can find the .so library file which we are going to use. Also, you can find the .jar file for java under the created build folder.

First, we need to load the ITK .jar file in our project and .so file by providing the JVM argument as
Djava.library.path=/path/to/SimpleITKRuntime
Where, /path/to/SimpleITKRuntime is the directory that contains the .so file. Otherwise, you will get the following error
Exception in thread "main" java.lang.UnsatisfiedLinkError: no SimpleITKJava in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
	at java.lang.Runtime.loadLibrary0(Runtime.java:871)
	at java.lang.System.loadLibrary(System.java:1124)
	at org.itk.simple.SimpleITKJNI.<clinit>(SimpleITKJNI.java:226)
	at org.itk.simple.SimpleITK.readImage(SimpleITK.java:475)
	at simpleitk.SimpleItkTest.main(SimpleItkTest.java:8)

Run the sample Java example

package simpleitk;

import org.itk.simple.Image;
import org.itk.simple.SimpleITK;

public class SimpleItkTest {
    public static void main(String[] args) {
		String inputImagePath = "/path/to/image";
		String outputImagePath = "/path/to/output/image";
        Image image = SimpleITK.readImage(inputImagePath);
        SimpleITK.writeImage(image, outputImagePath);
    }
}

This is a sample example for reading and writing images using simpleITK library.

Note if we are using the Gradle project, then we can add the .so library path as below

bootRun {
    jvmArgs('-Djava.library.path=/opt/SimpleItk/')
}
Where, /opt/SimpleItk/ is the directory which contains the .so file.

Share:

Wednesday, June 3, 2020

Convert Tiff file to JPG/PNG using Java.

How to convert a tiff(tif) file to JPG/PNG using Java.

While dealing with the tiff file, we may have the problem that some browser doesn't support it. Please visit for image format support for different browser here. In this tutorial, we are going to convert the tiff file to a jpg or png file format in an efficient way.



Dependencies required.

In order to convert tiff to other image formats, we are using Jai image i/o  library. Download the jar file from here. As we are using lib version "jai-imageio-core-1.4.0" here, you can find jar file under Assets. Load the jar file in your IDE or if you have existing projects like Maven or Gradle add the dependency as below.

For Gradle:

Add in build.gradle under "dependencies"
compile 'com.github.jai-imageio:jai-imageio-core:1.4.0'

For Maven:

Add in pom.xml
 <dependencies>
    <dependency>
        <groupid>com.github.jai-imageio</groupid>
        <artifactid>jai-imageio-core</artifactid>
        <version>1.4.0</version>
    </dependency>
</dependencies>

Convert Tiff to PNG/JPG

Let's create a class called "TiffConverter.java"

TiffConverter.java:
public static void main(String[] args) {
        File tiffFile = new File("/home/360learntocode/im.tif"); //input path to tif file
        String outputPath = "/home/360learntocode/"; //output path to write file
        String convertFormat = "jpg"; //jpg, png, bmp
        try {
            TiffConverter.convertTiff(tiffFile, outputPath, convertFormat);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Provide the appropriate input and output path. You can provide the desired conversion format. As the conversion will reduce the pixel value of the image for jpg, png although BMP conversion doesn't reduce the pixel value.
private static File convertTiff(File tiffFile, String outputPath, String convertFormat) throws IOException {
        String fileName = tiffFile.getName();
        String ext = getFileExtension(fileName);
        fileName = fileName.replace(ext, "."+convertFormat);
        BufferedImage tiff = ImageIO.read(tiffFile);
        File output = new File(outputPath + fileName);
        ImageIO.write(tiff, convertFormat, output);
        return output;
    }





We are using the library to manipulate and convert the tif file. BufferedImage is used to handle and manipulate the image data. For more visit here.

  //get file extension from file name
    private static String getFileExtension(String fileName) {
        int lastIndexOf = fileName.lastIndexOf(".");
        return fileName.substring(lastIndexOf).toLowerCase();
    }
 

Finally, we successfully converted the Tiff/Tif File to the desired format like jpg, png, BMP.

The overall implementation looks like as below:
 import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;


public class TiffConverter {

    public static void main(String[] args) {
        File tiffFile = new File("/home/360learntocode/im.tif"); //input path to tif file
        String outputPath = "/home/360learntocode/"; //output path to write file
        String convertFormat = "jpg"; //jpg, png, bmp
        try {
            TiffConverter.convertTiff(tiffFile, outputPath, convertFormat);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static File convertTiff(File tiffFile, String outputPath, String convertFormat) throws IOException {
        String fileName = tiffFile.getName();
        String ext = getFileExtension(fileName);
        fileName = fileName.replace(ext, "."+convertFormat);
        BufferedImage tiff = ImageIO.read(tiffFile);
        File output = new File(outputPath + fileName);
        ImageIO.write(tiff, convertFormat, output);
        return output;
    }

    //get file extension from file name
    private static String getFileExtension(String fileName) {
        int lastIndexOf = fileName.lastIndexOf(".");
        return fileName.substring(lastIndexOf).toLowerCase();
    }
}
Share: