How can I segment a colored line? - java

I'm trying to segment the blue and black line of this image.
original image
but I was unable to segment them separately (using the OpenCV library in Java) and it resulted in this:
binarized image
I tried this function:
mgproc.threshold(imgGray, imgThreshold, 0, 255, Imgproc.THRESH_BINARY + Imgproc.THRESH_OTSU);
How can I segment the blue and black lines separately using the OpenCV library?

If the colors of the lines are a given, you can define a color range and filter the image.
Here is a sample code (not mine; taken from this website: https://pythonprogramming.net/color-filter-python-opencv-tutorial/)
lower_red = np.array([30,150,50])
upper_red = np.array([255,255,180])
mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(frame,frame, mask= mask)
cv2.imshow('frame',frame)
cv2.imshow('mask',mask)
cv2.imshow('res',res)

Try using adaptiveThreshold, and tune to your needs.
// Adaptive Threshold
Imgproc.adaptiveThreshold(test_image, test_image, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C,
Imgproc.THRESH_BINARY_INV, 15,2);
See more Java examples

Related

is it right to use batcher.drawSprite to draw all images in game?

I'm developing a game and use batcher.drawSprite method to draw all images in the game (background and all characters)
in assets.java :
charAtlas = new Texture(game, "charAtlas.png");
charEnemy = new TextureRegion(charAtlas, 0,0,250,300);
in worldGame.java :
batcher.beginBatch(Assets.charAtlas); // set atlas
batcher.drawSprite(130, 628, 120,140, Assets.charEnemy);
//assets.charEnemy
is it right to use this method in all condition ?
I have 3 atlas in game , i even use 2048x2048 atlas size so i can include all my images in there..
However, the image looks blurry in game (Tested in galaxy note, tab, and galaxy young). looks at the code above, i even have the enemy char take size in my atlas as much as 250x300 , it's not make sense that it'll look blurry as i only draw it in 120x140.
note : i use no layout (i mean no layout file in res folder) .. i use drawsprite to draw all image (Character,menu, button, etc)..
update :
I tried to use character image files from other game that i unzipped, when i run the app, it also looks blurry and jagged. while in the original game, it's so smooth and sharp. why is that ?
check your code, you might use scaledbitmap , see if you can set like this.
Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap source = BitmapFactory.decodeResource(a.getResources(), path, options);

Using method convertTo in opencv java wrapper

any body please help me to understand how to use method convertTo in JavaCV. i was trying and searching a lot of time and not find the proper answer. so my problem is, when i try to convert type of mat from gray image to CV_32F and try to display it in android screen it will give me no result. this my source :
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGBA2GRAY, 1); // dst is gray image
dst.convertTo(dst_f, CvType.CV_32F, 1./255, 0); //convert dst to CV_32F with optional scale
Imgproc.cvtColor(dst_f, src, Imgproc.COLOR_GRAY2RGBA, 4); // to display it in android before convert to bitmap
I was trying also in opencv C++ with this code and it run smoothly :
imshow("dst", image);
cvtColor(image, dst, CV_BGR2GRAY);
dst.convertTo(dst_f, CV_32F, 1.0/255, 0);
imshow("dst_f", dst_f);
UPDATED :
I think i wrong when i try to display image online in android screen. i don't know how to display it altough i knew that android need 4 channel to display image in screen. but when i convert gray to CV_32F image type and i try to display with same code like above and it run smoothly without no result.
After some research and Experiment, i just got my golden answer, here it is :
Android can only display 4 channels image in the screen so you need to convert it to 4 channels (RGBA), but before you convert to RGBA/BGRA you have to change Mat image to CV_8U with same scaled. just look at this example :
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGBA2GRAY, 1);
dst.convertTo(dst_f, CvType.CV_32F, 1./255, 0);
dst_f.convertTo(final, CvType.CV_8U, 255, 0);
Imgproc.cvtColor(final, src, Imgproc.COLOR_GRAY2RGBA, 4);
With above code, your code will work perfectly in Android screen, but it will give you a broken picture if you try to save it to jpg image or other picture extension. if you want to save it to sdcard you can use this source :
Imgproc.cvtColor(src, dst, Imgproc.COLOR_RGB2GRAY, 1);
dst.convertTo(dst_f, CvType.CV_32F, 1.0/255, 0); // Convert Mat image to CV_32F and scale it to 1.0/255
dst_f.convertTo(final, CvType.CV_32F, 255, 0); //Convert it Back to Default type before
Imgproc.cvtColor(final, roi, Imgproc.COLOR_GRAY2RGB, 0);
Imgproc.cvtColor(roi, roi, Imgproc.COLOR_RGB2RGBA, 0);
above all is my own experiment, if you wanna ask me something, i will answer as good as i can. Thanks. Hope this help others a lot

Encoding transparent animated gif in Java

I am using GifDecoder to read an animated .gif file and AnimGifEncoder to write it. (link)
If I display the original frames read by GifDecoder they display correctly and are transparent, but if I display the frames created by AnimatedGifEncoder the transparency is all wrong.
GifDecoder gif = new GifDecoder();
gif.read("image.gif");
AnimatedGifEncoder e = new AnimatedGifEncoder();
e.start("newimage.gif");
e.setTransparent(Color.BLACK);
for (int i=0;i<gif.getFrameCount();i++) {
anim.addFrame(gif.getFrame(i));
anim.setDelay(gif.getDelay(i));
}
anim.finish();
In this example I set the transparent color to black. But actually I want to get the transparent color information from the GifDecoder but I don't know how.
I'm using the following solution, although there are still some gif files that
are a mess after scaling... :
(At least it seems to get along with most non-transparent gifs)
Color transparentColor = null;
BufferedImage firstFrameImage = ImageIO.read([sourceFileHere]);
if (firstFrameImage.getColorModel() instanceof IndexColorModel) {
IndexColorModel cm = (IndexColorModel) firstFrameImage.getColorModel();
int transparentPixel = cm.getTransparentPixel();
transparentColor = new Color(cm.getRGB(transparentPixel), true);
}
e.setTransparent(transparentColor);
This was all a long time ago, but I did manage to get it working at the time. Without digging out the code again... I got it working by:
Scan the original image and set the transparent areas to a colour that does not exist inside the original image.
Set the transparent colour inside the AnimGifEncoder to the colour that was previously assigned to the transparent areas.

OpenCV how can i detect webcam and compare the local file to match face

The highlighted code demonstrate openCV framework is loaded in my C code and it render Police watching. Which is just to demonstrate it works very smooth and very clean code to write.
Target:
My webCAM is connected in to the USB port. I would like to capture the live webcam image and match from a local file (/tmp/myface.png), if live webcam match with local file myface.png, it will show the text "Police watching"
My Questions to fix:
1) How can i now, capture my webCAM on this following code?
2) When the webCAM is captured, how can i load the file and find if it match, on match it shows that text only.
#include "cv.h"
#include "highgui.h"
int main()
{
CvPoint pt = cvPoint( 620/4, 440/2 ); // width, height
IplImage* hw = cvCreateImage(cvSize(620, 440), 8,3); // width, height
CvFont font; // cvSet(hw,cvScalar(0,0,0)); // optional
cvInitFont (&font, CV_FONT_HERSHEY_COMPLEX, 1.0, 1.0, 0, 1, CV_AA);
cvPutText (hw, "Police watching", pt, &font, CV_RGB(150, 0, 150));
cvShowImage("Police watching", hw); //cvNamedWindow("Police watching", 0); // optional
cvWaitKey (0);
}
Note: When this model will work i will practice this to convert in to JNI java model.
Capturing a video frame is simple just follow this example. The essential part is:
IplImage *img = cvLoadImage( argv[1], CV_LOAD_IMAGE_COLOR );
CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
while ( 1 ) {
IplImage* frame = cvQueryFrame( capture );
//match(img,frame);
}
cvReleaseCapture( &capture );
The second part is probably much harder and depends on what exactly are you trying to do. If you want to simply compare images, you can use cvNorm. If you want face detection or face recognition you really need to know what are you doing.
This is how I get a webcam feed... (the code is in Python but is easily translated)
# create capture device
device = 0 # assume we want first device
capture = cv.CreateCameraCapture(0)
cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH, 640)
cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, 480)
# check if capture device is OK
if not capture:
print "Error opening capture device"
sys.exit(1)
# capture the current frame
frame = cv.QueryFrame(capture)
if frame is None:
break
# mirror
cv.Flip(frame, None, 1)
#Do face detection here
I think you'll have an incredibly hard time trying to match a face from a single file to a live video stream. Look into cv.HaarDetectObjects for some cool feature detection algorithms.

Median Filter a bi-level image with JAI

I'd like to apply a Median Filter to a bi-level image and output a bi-level image. The JAI median filter seems to output an RGB image, which I'm having trouble downconverting back to bi-level.
Currently I can't even get the image back into gray color-space, my code looks like this:
BufferedImage src; // contains a bi-level image
ParameterBlock pb = new ParameterBlock();
pb.addSource(src);
pb.add(MedianFilterDescriptor.MEDIAN_MASK_SQUARE);
pb.add(3);
RenderedOp result = JAI.create("MedianFilter", pb);
ParameterBlock pb2 = new ParameterBlock();
pb2.addSource(result);
pb2.add(new double[][]{{0.33, 0.34, 0.33, 0}});
RenderedOp grayResult = JAI.create("BandCombine", pb2);
BufferedImage foo = grayResult.getAsBufferedImage();
This code hangs on the grayResult line and appears not to return. I assume that I'll eventually need to call the "Binarize" operation in JAI.
Edit: Actually, the code appears to be stalling once I call getAsBufferedImage(), but returns nearly instantly when the second operation ("BandCombine") is removed.
Is there a better way to keep the Median Filtering in the source color domain? If not, how do I downconvert back to binary?
Unfortunately it seems like the BandCombine operation doesn't behave as expected here. The appropriate tactic for getting back to bilevel is to use a flavor of ColorConvertOp -- doing so enables use of the MedianFilter operation which will (again, unfortunately) always lead to an RGB image.

Categories