Modify Mat object Pixel values by using OpenCV - java

I'm a beginner in Android Programming.I'm building an Android App for Image Steganography.I already developed this application for Desktop using Java and OpenCV,which works Perfectly.I'm trying to re-use the code,which I have.
I created a Mat Object and passed it to the Java Class(which I already have).I'm able to read the Pixel Intensities in the Mat Object,But,when I'm trying to modify those values (by using put()),my app is getting crashed.
The Exception thrown was
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.hari.imagesteganography, PID: 8850
java.lang.UnsupportedOperationException: Provided data element number (3) should be multiple of the Mat channels count (4)
at org.opencv.core.Mat.put(Mat.java:954)
at com.example.hari.imagesteganography.LSBImageStego.encodeOriginalMessageBinaryLength(LSBImageStego.java:101)
at com.example.hari.imagesteganography.LSBImageStego.encodeImage(LSBImageStego.java:239)
at com.example.hari.imagesteganography.EncodeActivity$1.onClick(EncodeActivity.java:98)
at android.view.View.performClick(View.java:6302)
at android.view.View$PerformClick.run(View.java:24782)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6518)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
The same method (put()) works perfectly fine running on Desktop.
Following is my Code in the Android application.
private void encodeOriginalMessageBinaryLength(){
// LOGGING THIS,SHOWS THAT THE FUNCTION EXECUTION STARTED
Log.i("URI" , "encodeOriginalMessageBinaryLength()");
String binary_of_originalMessageBinaryLength = Integer.toBinaryString(this.originalMessageBinaryLength);
if(binary_of_originalMessageBinaryLength.length()%2 !=0){
binary_of_originalMessageBinaryLength = "0" + binary_of_originalMessageBinaryLength;
}
int remaining = binary_of_originalMessageBinaryLength.length();
String newLsbBits;
for(int col = this.coverImage_cols -1 ; col >=0 ; col--){
if(remaining > 0){
newLsbBits = binary_of_originalMessageBinaryLength.substring( remaining - NUMBER_OF_BITS_REPLACING , remaining );
remaining -= NUMBER_OF_BITS_REPLACING;
}else{
newLsbBits = String.join("", Collections.nCopies(NUMBER_OF_BITS_REPLACING, "0"));
}
Log.i("URI","newLsbBits"+newLsbBits);
String modifiedBinaryString = this.getBeautifiedBinaryString(this.coverImage.get( this.coverImage_rows -1,col )[0]).substring(0 , this.getBeautifiedBinaryString(this.coverImage.get( this.coverImage_rows -1,col )[0]).length() - NUMBER_OF_BITS_REPLACING) + newLsbBits;
Log.i("URI","modifiedBianryString"+modifiedBinaryString);
double[] data = new double[3];
data[0] = Integer.parseInt(modifiedBinaryString , 2);
data[1] = this.coverImage.get( this.coverImage_rows -1,col )[1];
data[2] = this.coverImage.get( this.coverImage_rows -1,col )[2];
this.coverImage_rows -1,col )[0]);
// LOGGING THE DIMENSIONS OF THE IMAGE CORRECTLY,SHOWS THAT THE Mat Object
// IS INITIALIZED CORRECTLY
Log.i("URI" , new Integer(this.coverImage_rows).toString());
Log.i("URI" , new Integer(this.coverImage_cols).toString());
// EXECUTING BELOW LINE CAUSES THE APP TO CRASH
this.coverImage.put( this.coverImage_rows -1,col , data);
// BELOW MESSAGE IS NOT BEING LOGGED
Log.i("URI" , "encodeOriginalMessageBinaryLength() END");
}
}
The Corresponding Logcat log is as follows.
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: encodeOriginalMessageBinaryLength()
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: newLsbBits10
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: modifiedBianryString10010110
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: 1440
2019-02-08 12:30:37.019 1230-1230/com.example.hari.imagesteganography I/URI: 2560
The Mat Object and other attributes are being set as follows
public LSBImageStego(Mat coverImage){
this.coverImage = coverImage;
this.coverImage_rows = (int)coverImage.size().height;
this.coverImage_cols = (int)coverImage.size().width;
}
Is my code wrong?How to change Pixel Intensity values of Mat Object using OpenCV and Java in Android?
I believe that,this question is not duplicate of Using get() and put() to access pixel values in OpenCV for Java
OR
opencv java modify pixel values
,as they are not intended for Android, and the put() method described in those questions,works fine even for me on Desktop.

Method put() is overloaded in Mat class.
For each Mat type a specific data type is required.
For example, if you Mat type is CV_32S the data required is int [].
You can check the implementation of Mat class for all Mat types.

Related

How to fix Integer.intValue() for RTL languages in Android

In my application I write some codes and this codes I used string.
I want use UTF-8 languages (Farsi), But after run application show me error and force close application.
But when use English language not show me any error and run successfully!!
My codes :
this.q.put("dry land swim", Integer.valueOf(R.array.dry_land_swim));
TypedArray obtainTypedArray = getResources().obtainTypedArray(((Integer) this.q.get(stringArray[i])).intValue());
int length = obtainTypedArray.length();
int[] iArr2 = new int[length];
WorkoutData workoutData = new WorkoutData();
for (int i2 = 0; i2 < length; i2++) {
iArr2[i2] = obtainTypedArray.getResourceId(i2, -1);
}
workoutData.setExcName(stringArray[i]);
Log.e("ShowError", "" + (this.r.get(stringArray[i])).intValue());
workoutData.setExcDescResId(((Integer) this.r.get(stringArray[i])).intValue());
When change this line text (from En to Fa) :
this.q.put("تست", Integer.valueOf(R.array.dry_land_swim));
Show me error for this lines :
TypedArray obtainTypedArray = getResources().obtainTypedArray(((Integer) this.q.get(stringArray[i])).intValue());
workoutData.setExcDescResId(((Integer) this.r.get(stringArray[i])).intValue());
Error message :
java.lang.RuntimeException: Unable to start receiver com.crazytrends.healthmanager.WalkandStep.receivers.HardwareStepCountReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.crazytrends.healthmanager/.WalkandStep.services.HardwareStepCounterService }: app is in background uid UidRecord{528e8bd u0a841 RCVR idle change:idle|uncached procs:1 seq(0,0,0)}
at android.app.ActivityThread.handleReceiver(ActivityThread.java:4452)
at android.app.ActivityThread.access$1600(ActivityThread.java:301)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2159)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:246)
at android.app.ActivityThread.main(ActivityThread.java:8512)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.crazytrends.healthmanager/.WalkandStep.services.HardwareStepCounterService }: app is in background uid UidRecord{528e8bd u0a841 RCVR idle change:idle|uncached procs:1 seq(0,0,0)}
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1795)
at android.app.ContextImpl.startService(ContextImpl.java:1740)
at android.content.ContextWrapper.startService(ContextWrapper.java:738)
at android.content.ContextWrapper.startService(ContextWrapper.java:738)
at com.crazytrends.healthmanager.WalkandStep.receivers.HardwareStepCountReceiver.onReceive(HardwareStepCountReceiver.java:22)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:4443)
How can I Fix it?

OpenCV 2.4 Bilateral filtering

In OpenCV android, is it possible to apply bilateral filtering? I know that I can do gaussian blurring like Imgproc.GaussianBlur(gray, gray, new Size(15,15), 0); but I cannot seem to find the code for bilateral filtering.
Seems it's possible like:
Imgproc.bilateralFilter(mat, dstMat, 10, 50, 0);
from here and here.
Update
This:
E/AndroidRuntime: FATAL EXCEPTION: Thread-1376 Process: PID: 30368 CvException [org.opencv.core.CvException: cv::Exception: /Volumes/build-storage/build/2_4_pack-android/opencv/modules‌​/imgproc/src/smooth.‌​cpp:1925: error: (-215) (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.type() == dst.type() && src.size() == dst.size() && src.data != dst.data in function void cv::bilateralFilter_8u(const cv::Mat&, cv::Mat&, int, double, double, int)
is because wrong color format of processing Mat. You should convert 4 channels RGBA format to 3 channels RGB for bilateralFilter() apply (like in bilateralFilterTutorial() method here). So, You code should be like that:
// load Mat from somewhere (e.g. from assets)
mSourceImageMat = Utils.loadResource(this, R.drawable.<your_image>);
// convert 4 channel Mat to 3 channel Mat
Imgproc.cvtColor(mSourceImageMat, mSourceImageMat, Imgproc.COLOR_BGRA2BGR);
// create dest Mat
Mat dstMat = mSourceImageMat.clone();
// apply bilateral filter
Imgproc.bilateralFilter(mSourceImageMat, dstMat, 10, 250, 50);
// convert to 4 channels Mat back
Imgproc.cvtColor(dstMat, dstMat, Imgproc.COLOR_RGB2RGBA);
// create result bitmap and convert Mat to it
Bitmap bm = Bitmap.createBitmap(mSourceImageMat.cols(), mSourceImageMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(dstMat, bm);
// show bitmap on ImageView
mImageView.setImageBitmap(bm);
The problem could be, that you use PNG image, which has a 4th channel for transparency. Convert it from 4 channel to 3 channel, before use.
Imgproc.cvtColor(src,dst,Imgproc.COLOR_BGRA2BGR);

Java GRIB-Decoder: Extract data from GRIB2 files

I've downloaded some grib data files from here: ftp://data-portal.ecmwf.int/20160721000000/ (file type is .bin) and want to extract the data from this file in my Java application (I want to load the extracted data into a database later). I'm just trying with the file ftp://wmo:essential#data-portal.ecmwf.int/20160721000000/A_HWXE85ECEM210000_C_ECMF_20160721000000_24h_em_ws_850hPa_global_0p5deg_grib2.bin.
Therefore I've created a new Java project and added the two libraries grib-8.0.29.jar and netcdfAll-4.6.6.jar. Documentation for the grib API can be found here: http://www.unidata.ucar.edu/software/decoders/grib/javadoc/. I need to open the downloaded files to get the data. Retrieving some metadata via Grib2Dump seems to work (see below). Also the Grib2Input instance sais, that I have a valid GRIB file of version 2.
Here my working code for retrieving some metadata:
public static void main(String[] args) throws IOException, InterruptedException {
File srcDir = new File("C://test//");
File[] localFiles = srcDir.listFiles();
for (File tempFile : localFiles) {
RandomAccessFile raf = new RandomAccessFile(tempFile.getAbsolutePath(), "r");
System.out.println("======= Grib2GDSVariables ==========");
Grib2GDSVariables gdsVariables = new Grib2GDSVariables(raf.readBytes(raf.read()));
System.out.println("Gds key : " + gdsVariables.getGdsKey());
System.out.println("======= Grib2Input ==========");
Grib2Input input = new Grib2Input(raf);
System.out.println(Grib2Input.isValidFile(raf));
System.out.println("scan : " + input.scan(true, true));
System.out.println("getGDSs.size: " + input.getGDSs().size());
System.out.println("getProducts.size: " + input.getProducts().size());
System.out.println("getRecords.size: " + input.getRecords().size());
System.out.println("edition: " + input.getEdition());
System.out.println("======= Grib2Dump ==========");
Grib2Dump dump = new Grib2Dump();
dump.gribDump(new String[] {tempFile.getAbsolutePath()});
System.out.println("======= Grib2ExtractRawData ==========");
Grib2ExtractRawData extractRawData = new
Grib2ExtractRawData(raf); extractRawData.main(new String[] {tempFile.getAbsolutePath()});
}
System.out.println("finished");
}
This produces the following output:
======= Grib2GDSVariables ==========
Gds key : -1732955898
======= Grib2Input ==========
true
scan : true
getGDSs.size: 0
getProducts.size: 0
getRecords.size: 0
edition: 2
======= Grib2Dump ==========
--------------------------------------------------------------------
Header : GRIB2
Discipline : 0 Meteorological products
GRIB Edition : 2
GRIB length : 113296
Originating Center : 98 European Center for Medium-Range Weather Forecasts (RSMC)
Originating Sub-Center : 0
Significance of Reference Time : 1 Start of forecast
Reference Time : 2016-07-21T00:00:00Z
Product Status : 0 Operational products
Product Type : 1 Forecast products
Number of data points : 259920
Grid Name : 0 Latitude_Longitude
Grid Shape: 6 Earth spherical with radius of 6,371,229.0 m
Number of points along parallel: 720
Number of points along meridian: 361
Basic angle : 0
Subdivisions of basic angle: -9999
Latitude of first grid point : 90.0
Longitude of first grid point : 0.0
Resolution & Component flags : 48
Winds : True
Latitude of last grid point : -90.0
Longitude of last grid point : 359.5
i direction increment : 0.5
j direction increment : 0.5
Grid Units : degrees
Scanning mode : 0
Product Definition : 2 Derived forecast on all ensemble members at a point in time
Parameter Category : 2 Momentum
Parameter Name : 1 Wind_speed
Parameter Units : m s-1
Generating Process Type : 4 Ensemble Forecast
ForecastTime : 24
First Surface Type : 100 Isobaric surface
First Surface value : 85000.0
Second Surface Type : 255 Missing
Second Surface value : -9.999E-252
======= Grib2ExtractRawData ==========
finished
I tried around for two days now but couldn't get it to work! I can't obtain the content data (lat, lon, value) from the file...
Can someone give an example in Java?
You shouldn't use the GRIB classes in netCDF-java directly. Instead, use
NetcdfFile.open()
That will give you access through the CDM, giving you a straightforward interface with variables and attributes. There's a tutorial here: https://www.unidata.ucar.edu/software/thredds/current/netcdf-java/tutorial/NetcdfFile.html

How to find the local maxima and minima in an image

I am learning how to get the local and global maximum in an image, and as far as know, in one image there is only one global Maximum and one global minimum, and i managed to get these values and their corresponding locations in the image. so my questions are:
how to get the local maxima in an image
how to get the local minima in an image
as you see in the code below, I am using mask, but at run time i receieve the below mentioned error message. so please let me know why do we need mask and how to use it properly.
update:
Line 32 is: MinMaxLocResult s = Core.minMaxLoc(gsMat, mask);
code:
public static void main(String[] args) {
MatFactory matFactory = new MatFactory();
FilePathUtils.addInputPath(path_Obj);
Mat bgrMat = matFactory.newMat(FilePathUtils.getInputFileFullPathList().get(0));
Mat gsMat = SysUtils.rgbToGrayScaleMat(bgrMat);
Log.D(TAG, "main", "gsMat.dump(): \n" + gsMat.dump());
Mat mask = new Mat(new Size(3,3), CvType.CV_8U);//which type i should set for the mask
MinMaxLocResult s = Core.minMaxLoc(gsMat, mask);
Log.D(TAG, "main", "s.maxVal: " + s.maxVal);//to get the global maximum
Log.D(TAG, "main", "s.minVal: " + s.minVal);//to get the global minimum
Log.D(TAG, "main", "s.maxLoc: " + s.maxLoc);//to get the coordinates of the global maximum
Log.D(TAG, "main", "s.minLoc: " + s.minLoc);//to get the coordinates of the global minimum
}
error message:
OpenCV Error: Assertion failed (A.size == arrays[i0]->size) in cv::NAryMatIterator::init, file ..\..\..\..\opencv\modules\core\src\matrix.cpp, line 3197
Exception in thread "main" CvException [org.opencv.core.CvException: ..\..\..\..\opencv\modules\core\src\matrix.cpp:3197: error: (-215) A.size == arrays[i0]->size in function cv::NAryMatIterator::init
]
at org.opencv.core.Core.n_minMaxLocManual(Native Method)
at org.opencv.core.Core.minMaxLoc(Core.java:7919)
at com.example.globallocalmaxima_00.MainClass.main(MainClass.java:32)
In order to calculate global min/max values you don't need to use mask completely.
For calculating local min/max values you can do a little trick. You need to perform dilate/erode operation and then compare pixel value with values of original image. If value of original image and dilated/eroded image are equal therefore this pixel is local min/max.
The code is following:
Mat eroded = new Mat();
Mat dilated = new Mat();
Imgproc.erode(gsMat, eroded, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5)));
Imgproc.dilate(gsMat, dilate, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5)));
Mat localMin = new Mat(gsMat.size(), CvType.CV_8U, new Scalar(0));
Mat localMax = new Mat(gsMat.size(), CvType.CV_8U, new Scalar(0));
for (int i=0; i<gsMat.height; i++)
for (int j=0; j<gsMat.width; j++)
{
if (gsMat.get(i,j) == eroded.get(i,j))
localMin.put(i,j,255);
if (gsMat.get(i,j) == dilated.get(i,j))
localMax.put(i,j,255);
}
Please note, I'm not a Java programmer. So, code is only illustration of algorithm.

OpenCV Java inpaint image format requirement

Been trying to get inpainting to work on Android,
int height = (int) viewMat.size().height;
int width = (int) viewMat.size().width;
Mat maskMat = new Mat();
maskMat.create(viewMat.size(), CvType.CV_8U);
maskMat.setTo(bColor);
Point r1 = new Point(width/2-width/10, height/2-height/10);
Point r2 = new Point(width/2+width/10, height/2+height/10);
Scalar color = new Scalar(1);
Core.rectangle(maskMat, r1, r2, color, Core.FILLED);
outMat.create(viewMat.size(), CvType.CV_8UC3);
viewMat.convertTo(outMat, CvType.CV_8UC3);
Photo.inpaint(outMat, maskMat, outMat, 1, Photo.INPAINT_TELEA);
Was greeted with,
Caused by: CvException [org.opencv.core.CvException: /home/reports/ci/slave_desktop/50-SDK/opencv/modules/photo/src/inpaint.cpp:744:
error: (-210) Only 8-bit 1-channel and 3-channel input/output images are supported in function void cvInpaint(const CvArr*, const CvArr*, CvArr*, double, int)
in logcat.
Been trying for hours creating Mats in various ways but to no valid.
CV_8U = 8 bit per channel, 1 channel. Right?
CV_8UC3 = 8 bit per channel, 3 channels. Right?
So what am I missing? I'm totally stumped.
...
Point r2 = new Point(width/2+width/10, height/2+height/10);
Scalar color = new Scalar(1);
Core.rectangle(maskMat, r1, r2, color, Core.FILLED);
Imgproc.cvtColor(viewMat, outMat, Imgproc.COLOR_RGBA2RGB);
Photo.inpaint(outMat, maskMat, outMat, 1, Photo.INPAINT_TELEA);
...
Turned out it was simply a matter of getting rid of the alpha channel via color conversion.
Image Inpaint Using OpenCv Android Studio
ImgMat = Mat()
Maskmat = Mat()
destmat=Mat()
Utils.bitmapToMat(BitmapImage, ImgMat)
Utils.bitmapToMat(BitmapMask, Maskmat)
Imgproc.cvtColor(ImgMat, ImgMat, Imgproc.COLOR_RGB2XYZ)
Imgproc.cvtColor(Maskmat, Maskmat, Imgproc.COLOR_BGR2GRAY)
Photo.inpaint(ImgMat,Maskmat,destmat, 15.0, INPAINT_NS)
InpaintBitmap= Bitmap.createBitmap(BitmapImage.getWidth(),
BitmapImage.getHeight(),
Bitmap.Config.ARGB_8888)
Imgproc.cvtColor(destmat, destmat, Imgproc.COLOR_XYZ2RGB);
Utils.matToBitmap(destmat, InpaintBitmap)
Description:
InpaintBitmap is an Inpaint color Bitmap
src image is a 3 channel image but mask bitmap is a 1 channel image

Categories

Resources