m00sedrive / javacv

Automatically exported from code.google.com/p/javacv
GNU General Public License v2.0
0 stars 0 forks source link

[Android + JavaCV] Bitmap <-> IplImage #67

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Hello samuel,

I want convert IplImage to Bitmap.
I saw #59 issue. But I can't translate IplImage to bitmap.

What steps will reproduce the problem?
1. JavaCV sample source modify(faceview.java)
2. Used the "cvFindContours" function
3. I want get the result IplImage of "cvDrawContours"

What is the expected output? What do you see instead?
I want see the result bitmap(from iplimage) at Android.

What version of the product are you using? On what operating system?
Android(2.2 - Optimus 2x) + JavaCV

Please provide any additional information below.
I attach a file source code. I have some test in source.
My source is dirty. But help me~ plz.

Original issue reported on code.google.com by indy0...@gmail.com on 12 May 2011 at 8:38

Attachments:

GoogleCodeExporter commented 8 years ago
That would be a request for enhancement, not a defect. However, it's pretty 
easy to convert an IplImage to a Bitmap, so I'm not sure we need anything 
special in JavaCV. Can you try the following?

We should be able to transfer data by simply calling
    Bitmap.copyPixelsFromBuffer(IplImage.getByteBuffer());
but the pixel formats need to match, which seems to be 32-bit ARGB888 in the 
case of Android, so an IplImage of IPL_DEPTH_8U with 4 channels should do the 
trick.

Original comment by samuel.a...@gmail.com on 12 May 2011 at 11:06

GoogleCodeExporter commented 8 years ago
Really thank you, samuel. Thank you.

Original comment by indy0...@gmail.com on 13 May 2011 at 12:53

GoogleCodeExporter commented 8 years ago
Hi Guys!
I also have a problem with Bitmap <-> IplImage conversion.

When i run the code below and want to show the resulting Bitmap, I get an Image 
with two times the picture of the original Image... it looks like the picture 
is added another time on the right side of the original picture. Had any of you 
the same problem? 
Thanks a lot for any help!

try
{
   IplImage image = IplImage.create(width, height, IPL_DEPTH_8U, 4);

   //sourcImage is a Bitmap which comes from the sd-card of the emulator, 
   //from .jpg-file
   sourceImage.copyPixelsToBuffer(image.getByteBuffer());

   //smoothedImage is also a Bitmap created as follows
   //Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
   smoothedImage.copyPixelsFromBuffer(image.getByteBuffer());

}catch (Exception e) 
{
   //this is the line of code that sends a real error message to the log.
   Log.e("ERROR", "ERROR in Code: " + e.toString());

   e.printStackTrace();
}   

Original comment by markus.f...@gmail.com on 16 May 2011 at 7:35

GoogleCodeExporter commented 8 years ago
sorry forgot some additional information.
I'm using JavaCV (javacv-bin-20110511) on Mac OS X 10.6.7 with eclipse and 
android sdk.
OpenCV-2.2.0-android-arm and android-ndk-r4-crystax.

Original comment by markus.f...@gmail.com on 16 May 2011 at 8:26

GoogleCodeExporter commented 8 years ago
I found a solution... The problem was that the camera captured image was in 
RGB_565 format and I had to convert it into ARGB_8888 via: 
argbImage = rgb565Image.copy(Config.ARGB_8888, true);

thx anyway

Original comment by markus.f...@gmail.com on 16 May 2011 at 4:13

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Android Bitmap's format and IplImage's format matching is very important.

IplImage image = IplImage.create(width, height, IPL_DEPTH_8U, 4);
IplImage _3image = IplImage.create(width, height, IPL_DEPTH_8U, 3);
IplImage _1image = IplImage.create(width, height, IPL_DEPTH_8U, 1);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

1. iplimage -> bitmap
bitmap.copyPixelsFromBuffer(image.getByteBuffer());

2. bitmap -> iplimage
bitmap.copyPixelsToBuffer(image.getByteBuffer());

3. iplimage(4channel) -> iplimage(3channel or 1channel)
cvCvtColor(image, _3image, CV_BGRA2BGR);
cvCvtColor(_3image, _1image, CV_RGB2GRAY);

--------------------------------------------------------------------------------
---
Create iplimage from Android's camera byte[] data

private IplImage _4iplToBitmap;
_4iplToBitmap = IplImage.create(width, height, IPL_DEPTH_8U, 4);

int [] _temp = new int[width*height];

if(_4iplToBitmap!= null){
     decodeYUV420SP(_temp, data, width, height);
     _4iplToBitmap.getIntBuffer().put(_temp);
}

protected void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int 
height) {
        int frameSize = width * height;
        for (int j = 0, yp = 0; j < height; j++) {
            int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
            for (int i = 0; i < width; i++, yp++) {
                int y = (0xff & ((int) yuv420sp[yp])) - 16;
                if (y < 0) y = 0;
                if ((i & 1) == 0) {
                    v = (0xff & yuv420sp[uvp++]) - 128;
                    u = (0xff & yuv420sp[uvp++]) - 128;
                }
                int y1192 = 1192 * y;

                int r = (y1192 + 1634 * v);
                int g = (y1192 - 833 * v - 400 * u);
                int b = (y1192 + 2066 * u);

                if (r < 0) r = 0; else if (r > 262143) r = 262143;
                if (g < 0) g = 0; else if (g > 262143) g = 262143;
                if (b < 0) b = 0; else if (b > 262143) b = 262143;

                rgb[yp] = 0xff000000 | ((b << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((r >> 10) & 0xff);
            }
        }
}

Original comment by indy0...@gmail.com on 17 May 2011 at 1:21

GoogleCodeExporter commented 8 years ago
It's also possible to convert the RGB_565 format with OpenCV's cvCvtColor():
    CV_BGR2BGR565  =12,
    CV_RGB2BGR565  =13,
    CV_BGR5652BGR  =14,
    CV_BGR5652RGB  =15,
    CV_BGRA2BGR565 =16,
    CV_RGBA2BGR565 =17,
    CV_BGR5652BGRA =18,
    CV_BGR5652RGBA =19,

    CV_GRAY2BGR565 =20,
    CV_BGR5652GRAY =21,

There is nothing for planar YUV though.

Original comment by samuel.a...@gmail.com on 17 May 2011 at 1:34

GoogleCodeExporter commented 8 years ago
Hey,

getting the following image when trying your code:

http://imageshack.us/f/832/testkm.jpg/

Would need immediate help...

Thanks in advance!

Original comment by sebilin...@gmail.com on 28 May 2011 at 7:50

GoogleCodeExporter commented 8 years ago
Check the source in JavaCV's samples facepreview.java

I think use the SUBSAMPLING_FACTOR.

public static final int SUBSAMPLING_FACTOR = 4;

Original comment by indy0...@gmail.com on 1 Jun 2011 at 1:12

GoogleCodeExporter commented 8 years ago
Thanks so far!

I get a grayimage now, how to obtain the colors?

Original comment by sebilin...@gmail.com on 1 Jun 2011 at 1:58

GoogleCodeExporter commented 8 years ago
If you are trying to use images from a Camera object, simply copy the bytes 
from the images as per the format that should be NV12 
http://www.fourcc.org/yuv.php#NV12 into what OpenCV usually wants, that is RGB 
24bpp http://www.fourcc.org/rgb.php#BI_RGB 

Original comment by samuel.a...@gmail.com on 1 Jun 2011 at 2:14

GoogleCodeExporter commented 8 years ago
The format is NV21, which shouldn't matter that much...

Is there an existing algorithm for such conversion?

Original comment by sebilin...@gmail.com on 1 Jun 2011 at 2:19

GoogleCodeExporter commented 8 years ago
FFmpeg's swscale can do the conversion.. I'm sure there are pure Java functions 
already made, but I haven't checked into it. FFmpeg would probably be more 
efficient anyway.

Original comment by samuel.a...@gmail.com on 2 Jun 2011 at 4:56

GoogleCodeExporter commented 8 years ago
I managed to decode the YUV data to an IPLImage.
Now I converted the IPLImage color space to HSV via:

IplImage iplHSV = IplImage.create(width, height, IPL_DEPTH_8U, 3);
cvCvtColor(iplImage, iplHSV, CV_BGR2HSV);

If I try to save it back to a Bitmap via

bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(iplHSV.getByteBuffer());

I get "java.lang.RuntimeException: Buffer not large enough for pixels"... 

Any ideas?

Original comment by sebilin...@gmail.com on 3 Jun 2011 at 5:40

GoogleCodeExporter commented 8 years ago
Bitmap.Config.ARGB_8888 is 4 channel.

Channel is Alpha, Red, Green, Blue. 
8888 is 1channel = 8bit => 8bit/8bit/8bit/8bit
8bit 4channel.

IplImage ipl2bitmap = IplImage.create(width, height, IPL_DEPTH_8U, 4);

Original comment by indy0...@gmail.com on 3 Jun 2011 at 10:47

GoogleCodeExporter commented 8 years ago
Thanks!

But the problem is, I can't convert it into HSV 4-channel IPLImage, as HSV only 
has 3 of them:

06-06 16:30:59.585: ERROR/AndroidRuntime(6608): java.lang.RuntimeException: 
Unknown exception.
06-06 16:30:59.585: ERROR/AndroidRuntime(6608):     at 
com.googlecode.javacv.cpp.opencv_imgproc.cvCvtColor(Native Method)

Original comment by sebilin...@gmail.com on 6 Jun 2011 at 2:32

GoogleCodeExporter commented 8 years ago
4channel -> 3channel -> HSV

cvCvtColor(4channel, 3channel, CV_BGRA2BGR);
cvCvtColor(3channel, hsv, CV_BGR2HSV);

Original comment by indy0...@gmail.com on 7 Jun 2011 at 1:01

GoogleCodeExporter commented 8 years ago
I have convert a bitmap to IplImage on a java file doing: 
argbImage = bitmap.copy(Config.ARGB_8888, true);
IplImage image = IplImage.create(w, h, IPL_DEPTH_8U, 4);
IplImage _3image = IplImage.create(w, h, IPL_DEPTH_8U, 3);
argbImage.copyPixelsToBuffer(image.getByteBuffer());
 cvCvtColor(image, _3image,CV_BGRA2BGR )

I passed this IplImage (_3image) as an argument of a native function. 

Using JNI, I can't use this IplImage in my function Funct(JNIEnv * env, jobject 
thiz, jobject img, jint w, jint h). The app is closed automaticaly when I try 
to do some modifications on the image (cvSetReal3D) or when I want to extract 
img Size using cvGetSize(img).

Any ideas?? thanks in advance.

Original comment by rafegasf...@gmail.com on 17 Oct 2011 at 11:26

GoogleCodeExporter commented 8 years ago
@rafegasf, I think you should look at JavaCPP to be able to define a native 
function such as with 
http://code.google.com/p/javacv/source/browse/trunk/javacv/src/com/googlecode/ja
vacv/cpp/cvkernels.java

Please post other questions you may have on the mailing list, thank you

Original comment by samuel.a...@gmail.com on 19 Oct 2011 at 3:26

GoogleCodeExporter commented 8 years ago
hi samuel,

thanks for your report. I think that i have defined my native function 
correctly:

import  com.google.javacv.cpp.opencv_core.IplImage;

public class NativeLib extends JavaMain() {
     public native IplImage funcition (IplImage img, float[] vector1, int [] vector2);
     static{
         System.loadLibrary("demo");
     }
}

but when I run on a terminal to create .h file needed by .cpp files:
javah -jni namePakage.NativeLibrary

i have an error:
javadoc: error - In doclet class com.sun.tools.javah.MainDoclet, method start 
has thrown an exception java.lang. reflect.InvocationTargetException 
com.sun.tools.javac.code.Symbol$CompletionFailuer: class file for 
com.googlecode.javacv.cpp.opencv_core not found

which is my mistake?

the only thing that I need is Convert the android.graphics.bitmap image to 
IplImage to do some opencv modifications in the nativeCode (JNI) and return the 
new image to Java code.
I have try a lot of things and the app doesn't works yet... 

if anybody knows how  I can do it, please, help me!

Thank you in advance!

Original comment by rafegasf...@gmail.com on 8 Nov 2011 at 4:09

GoogleCodeExporter commented 8 years ago
@rafegasf, please refer to the documentation of JavaCPP for some details about 
defining native functions, and please post your JavaCPP-related questions on 
JavaCPP's mailing list, not here, thank you.

If you only wish to convert an Android Bitmap to IplImage, you do not need to 
define a native function. Just copy the data, as demonstrated in some of the 
comments above.

Original comment by samuel.a...@gmail.com on 9 Nov 2011 at 8:24

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
If I want to use cvCanny, how can I convert the output to android Bitmap?

Original comment by booker0108@gmail.com on 10 Feb 2012 at 8:03

GoogleCodeExporter commented 8 years ago
Use cvConvertScale() to convert the resulting images back to 8-bit data first, 
then copy the 8-bit data to a Bitmap.

Original comment by samuel.a...@gmail.com on 11 Feb 2012 at 1:53

GoogleCodeExporter commented 8 years ago
sorry,i have writen an example use this library as:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main2);
        imageView = (ImageView) findViewById(R.id.imageView1);
        addButton = (Button) findViewById(R.id.buttonAdd);

        iplImage = cvLoadImage(filename);

        addButton.setOnClickListener(new OnClickListener() {

            public void onClick(View arg0) {
                long start = System.currentTimeMillis();
                if (iplImage != null) {
                    cvSmooth(iplImage, iplImage, CV_GAUSSIAN, 3);
                    bitmapDes.copyPixelsFromBuffer(iplImage.getByteBuffer());
                    cvSaveImage(filename, iplImage);
                    cvReleaseImage(iplImage);
                }
                imageView.setImageBitmap(bitmapDes);
            Log.d("Time","time : "+ (System.currentTimeMillis() - start ));
            }
        });
    }
and when i run it force close with log:
03-07 14:57:08.750: E/AndroidRuntime(16745): FATAL EXCEPTION: main
03-07 14:57:08.750: E/AndroidRuntime(16745): java.lang.RuntimeException: 
/home/saudet/workspace/android/OpenCV-2.3.1/modules/imgproc/src/smooth.cpp:1547:
 error: (-215) dst.size() == src.size() && (smooth_type == CV_BLUR_NO_SCALE || 
dst.type() == src.type()) in function void cvSmooth(const void*, void*, int, 
int, int, double, double)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
com.googlecode.javacv.cpp.opencv_imgproc.cvSmooth(Native Method)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
com.googlecode.javacv.cpp.opencv_imgproc.cvSmooth(opencv_imgproc.java:626)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
com.example.bitmap.test.ImageFilterOpenCV$1.onClick(ImageFilterOpenCV.java:61)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
android.view.View.performClick(View.java:2574)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
android.view.View$PerformClick.run(View.java:9223)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
android.os.Handler.handleCallback(Handler.java:587)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
android.os.Handler.dispatchMessage(Handler.java:92)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
android.os.Looper.loop(Looper.java:130)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
android.app.ActivityThread.main(ActivityThread.java:3691)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
java.lang.reflect.Method.invokeNative(Native Method)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
java.lang.reflect.Method.invoke(Method.java:507)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
03-07 14:57:08.750: E/AndroidRuntime(16745):    at 
dalvik.system.NativeStart.main(Native Method)
03-07 14:57:13.359: I/dalvikvm(16745): threadid=4: reacting to signal 3

it run on Window 7?
please help me,and 1 more,i don't know how to convert between CvArr and 
IplImage.
with cvSmooth() i use IplImage as CvArr , it accepted but with blur() it did 
not accept ??
Thanks

Original comment by nguyenngochoang89 on 7 Mar 2012 at 8:09

GoogleCodeExporter commented 8 years ago
hi,I want to know if there is anyone get the right-format Iplimage with the 
method given at comment #7?Thank you!

Original comment by fujiaoji...@gmail.com on 13 Mar 2012 at 7:22

GoogleCodeExporter commented 8 years ago
Sorry #27 it wont work and you wont have the solution to do it... I'm still 
waiting.

Original comment by alei...@gmail.com on 22 Mar 2012 at 5:51

GoogleCodeExporter commented 8 years ago
I cannot find cvLoadImage()

How can I solve it?

Original comment by booker0108@gmail.com on 4 Apr 2012 at 10:03

GoogleCodeExporter commented 8 years ago
I use this method to process a picture taken with a camera. I try to request 
the NV21 picture format, if it is supported, to avoid unnecessary 
compression/decompression. If it is not supported, I decode the JPEG as follows:

@Override
public void onPictureTaken(byte[] data, Camera camera) {
    Size size = camera.getParameters().getPictureSize();

    CvMat rgbImage;

    if (camera.getParameters().getPictureFormat() == ImageFormat.NV21) {
        if (size.height % 2 != 0)
            throw new RuntimeException("Odd height not supported");

        CvMat nv21Image = CvMat.create(size.height + (size.height/2), size.width, CV_8UC1);
        rgbImage = CvMat.create(size.height, size.width, CV_8UC3);

        nv21Image.getByteBuffer().put(data);
        cvCvtColor(nv21Image, rgbImage, CV_YUV2BGR_NV21);
        nv21Image.release();
    } else {
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
        if (bitmap.getConfig() == Bitmap.Config.RGB_565) {
            CvMat rgb565Image = CvMat.create(size.height, size.width, CV_8UC2);
            bitmap.copyPixelsToBuffer(rgb565Image.getByteBuffer());
            rgbImage = CvMat.create(size.height, size.width, CV_8UC3);
            cvCvtColor(rgb565Image, rgbImage, CV_BGR5652BGR);
            rgb565Image.release();
        }
        else if (bitmap.getConfig() == Bitmap.Config.ARGB_8888) {
            rgbImage = CvMat.create(size.height, size.width, CV_8UC4);
            bitmap.copyPixelsToBuffer(rgbImage.getByteBuffer());
        }
        else
            throw new RuntimeException("Unsupported bitmap config: " + bitmap.getConfig());

        bitmap.recycle();
    }

    // ... continue using rgbImage
}

Original comment by viliam.d...@gmail.com on 14 May 2013 at 8:11

GoogleCodeExporter commented 8 years ago
Thanks @indy0 for #16 !!

Original comment by iriarte....@gmail.com on 11 Jun 2014 at 6:22

GoogleCodeExporter commented 8 years ago
It took a while, but I've finally managed to figure out a nice to way to go 
about this:
http://bytedeco.org/news/2015/04/04/javacv-frame-converters/

So, JavaCV 0.11 now comes with `AndroidFrameConverter` and 
`OpenCVFrameConverter` to implement this functionality:
http://bytedeco.org/javacv/apidocs/org/bytedeco/javacv/AndroidFrameConverter.htm
l
http://bytedeco.org/javacv/apidocs/org/bytedeco/javacv/OpenCVFrameConverter.html
Enjoy!

Original comment by samuel.a...@gmail.com on 11 Apr 2015 at 2:07