Issue
This is my jni file , native.cpp
extern "C"
Java_org_opencv_samples_NativeActivity_CvNativeActivity_CannyJNI(
JNIEnv* env, jobject thiz,
jint height, jint width, jintArray in, jintArray out)
{
//get the data pointer.
jint* _in = env->GetIntArrayElements(in, 0);
jint* _out = env->GetIntArrayElements(out, 0);
//Build the Mat structure for input data
Mat mSrc(height, width, CV_8UC4, (unsigned char *)_in);
//Build the Mat structure for output data
Mat bgr(height, width, CV_8UC4, (unsigned char *)_out);
//Convert Mat to IplImage
IplImage mSrcImg = mSrc;
IplImage mOutImg = bgr;
//Create the gray image for input data.
IplImage * mSrcGrayImg = cvCreateImage(cvGetSize(&mSrcImg), mSrcImg.depth, 1);
IplImage * mOutGrayImg = cvCreateImage(cvGetSize(&mSrcImg), mSrcImg.depth, 1);
IplImage *b,*g,*r;
b = cvCreateImage( cvGetSize(mSrcGrayImg), 8, 1 );
g = cvCreateImage( cvGetSize(mSrcGrayImg), 8, 1 );
r = cvCreateImage( cvGetSize(mSrcGrayImg), 8, 1 ) ;
cvSplit(&mSrcImg, b, g, r, 0 );
cvEqualizeHist( b, b );
cvEqualizeHist( g, g );
cvEqualizeHist( r, r );
cvMerge(b,g,r,0,&mOutImg);
//release the pointer.
env->ReleaseIntArrayElements(in, _in, 0);
env->ReleaseIntArrayElements(out, _out, 0);
return true;
}
When i add these two lines my every jni part work for me
cvCvtColor(mOutGrayImg, mSrcGrayImg, CV_BGR2YCrCb);
cvCvtColor(mSrcGrayImg, &mOutImg , CV_YCrCb2BGR);
like from above code when i add
cvMerge(b,g,r,0,mOutGrayImg);
cvCvtColor(mOutGrayImg, mSrcGrayImg, CV_BGR2YCrCb);
cvCvtColor(mSrcGrayImg, &mOutImg , CV_YCrCb2BGR);
it runs , and same like my other codes , can anyone please tell me Why and How
? and How i can get rid of these two lines and simply cvMerge(b,g,r,0,mOutGrayImg);
this lines send the output image and how i can set the C++ interface for this code.
Here is my jave file contain CvNativeActivity.java
public class CvNativeActivity extends Activity implements CvCameraViewListener2
{
public native boolean BrightnessJNI(int width, int height, int [] mPhotoIntArray, int [] mCannyOutArray);
static
{
System.loadLibrary("native_activity");
}
/** Called when the activity is first created. */
ImageView imageview_1;
ImageView imageview_2;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageview_1=(ImageView) findViewById(R.id.imageView1);
imageview_2=(ImageView) findViewById(R.id.imageView2);
InputStream is;
is = this.getResources().openRawResource(R.drawable.foot);
Bitmap bmInImg = BitmapFactory.decodeStream(is);
int [] mPhotoIntArray;
int [] mCannyOutArray;
mPhotoIntArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];
// Copy pixel data from the Bitmap into the 'intArray' array
bmInImg.getPixels(mPhotoIntArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());
//create the Brightness result buffer
mCannyOutArray = new int[bmInImg.getWidth() * bmInImg.getHeight()];
//
// Do Brightness
//
BrightnessJNI(bmInImg.getHeight(), bmInImg.getWidth(), mPhotoIntArray, mCannyOutArray);
//
// Convert the result to Bitmap
//
Bitmap bmOutImg = Bitmap.createBitmap(bmInImg.getWidth(), bmInImg.getHeight(), Config.ARGB_8888);
bmOutImg.setPixels(mCannyOutArray, 0, bmInImg.getWidth(), 0, 0, bmInImg.getWidth(), bmInImg.getHeight());
imageview_2.setImageBitmap(bmOutImg);
//
// Save the result to file
//
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
String outFileName = extStorageDirectory + "/Brightness";
OutputBitmapToFile(bmOutImg, outFileName);
}
void OutputBitmapToFile(Bitmap InBm, String Filename)
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
InBm.compress(Bitmap.CompressFormat.PNG, 100, bytes);
File f = new File(Filename);
try
{
f.createNewFile();
//write the bytes in file
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Thanks
Solution
Well, I found the issue. It's not showing the image because you have put alpha channel
as 0 in cvMerge
. Bitmap is of RGBA format. And the alpha is 0. Hence complete black image.
Here's the C API implementation code. This works.
#include <jni.h>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include <opencv2/imgproc/imgproc_c.h>
using namespace std;
using namespace cv;
extern "C"
{
JNIEXPORT jint JNICALL
Java_com_fenchtose_equalizehist_EqActivity_eqhist(
JNIEnv* env, jobject,
jint width, jint height, jintArray in, jintArray out)
{
jint* _in = env->GetIntArrayElements(in, 0);
jint* _out = env->GetIntArrayElements(out, 0);
Mat mSrc(height, width, CV_8UC4, (unsigned char*)_in);
Mat bgra(height, width, CV_8UC4, (unsigned char*)_out);
IplImage mSrcImg = mSrc;
IplImage mOutImg = bgra;
IplImage *b, *g, *r, *a;
b = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);
g = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);
r = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);
a = cvCreateImage(cvSize(width, height), mSrcImg.depth, 1);
cvSplit(&mSrcImg, b, g, r, a);
cvEqualizeHist(b, b);
cvEqualizeHist(g, g);
cvEqualizeHist(r, r);
cvMerge(b, g, r, a, &mOutImg); // merge alpha layer too
jint retVal;
int ret = 1;
retVal = jint(retVal);
env->ReleaseIntArrayElements(in, _in, 0);
env->ReleaseIntArrayElements(out, _out, 0);
return retVal;
}
}
OLD ANSWER: I copied your Java file. Made some minor changes. (Showed original image in imageView1, changed native function call).
Here's the JNI File.
#include <jni.h>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <vector>
using namespace std;
using namespace cv;
extern "C"
{
JNIEXPORT jint JNICALL
Java_com_example_equalizehist_EqActivity_eqhist(
JNIEnv* env, jobject,
jint width, jint height, jintArray in, jintArray out)
{
jint* _in = env->GetIntArrayElements(in, 0);
jint* _out = env->GetIntArrayElements(out, 0);
Mat mSrc(height, width, CV_8UC4, (unsigned char*)_in);
Mat bgra(height, width, CV_8UC4);
vector<Mat> sChannels;
split(mSrc, sChannels);
for(int i=0; i<sChannels.size(); i++)
{
equalizeHist(sChannels[i], sChannels[i]);
}
merge(sChannels, bgra);
for(int i=0; i<height; i++)
{
memcpy(&(_out[i*width]), &(bgra.data[i*bgra.step]), width*bgra.channels());
}
env->ReleaseIntArrayElements(in, _in, 0);
env->ReleaseIntArrayElements(out, _out, 0);
jint retVal;
int ret = 1;
retVal = jint(retVal);
return retVal;
}
}
- Step1: Pass Pixel(int arrays) to native function.
- Step2: Create Mat with input pixels.
- Step3: Create an empty vector to hold each channel of
mSrc
Mat. - Step4: Split mSrc Mat to sChannels vector.
- Step5: Apply equalizeHist function on each channel. Loop over sChannels vector.
- Step6: Merge all the channels in bgra Mat.
- Step7: Copy data of
bgra
Mat to the array of pixels. For this usememcpy
. Iterate over each row ofbgra
Mat and copy data of each channel. This is CV_8UC4 Mat. Each channel will have data of 2 bytes. So Each pixel will contain 8 bytes of data. - Step8: Release arrays.
Here's the screenshot of the app.
I have put up this code on GitHub. You might want to check it if you run into any issues.
NOTE: If you're using this code, make sure that you declare the native function correctly.
If you don't want to use memcpy
, you can directly allocate
#include <jni.h>
#include <stdio.h>
#include "opencv2/core/core.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <vector>
using namespace std;
using namespace cv;
extern "C"
{
JNIEXPORT jint JNICALL
Java_com_example_equalizehist_EqActivity_eqhist(
JNIEnv* env, jobject,
jint width, jint height, jintArray in, jintArray out)
{
jint* _in = env->GetIntArrayElements(in, 0);
jint* _out = env->GetIntArrayElements(out, 0);
Mat mSrc(height, width, CV_8UC4, (unsigned char*)_in);
Mat bgra(height, width, CV_8UC4, (unsigned char*)_out);
vector<Mat> sChannels;
split(mSrc, sChannels);
for(int i=0; i<sChannels.size(); i++)
{
equalizeHist(sChannels[i], sChannels[i]);
}
merge(sChannels, bgra);
env->ReleaseIntArrayElements(in, _in, 0);
env->ReleaseIntArrayElements(out, _out, 0);
jint retVal;
int ret = 1;
retVal = jint(retVal);
return retVal;
}
}
Even this is working properly.
Answered By - Froyo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.