Webcam - detect QR code, take snapshot and decode - java

I am currently trying to write a java program to utilize either a built in laptop webcam or an external USB webcam. This would hopefully be compatible with both PC and Mac.
I was wondering if anyone knew of a library that can deal with it all? I don't really want to reinvent the wheel and I wouldn't have any idea where to start in 1) detecting a webcam, 2) taking a snapshot when a QR code is detected.
I am familiar with ZXing for decoding barcode images however.
I have searched high and low, I strongly suspect the library I look for doesn't exist, however its worth an ask!
My first question on here, so I hope it is clear!
edit: alternatively, if one doesn't exist, could you point me in the right direction of how to take a snapshot from webcam when a QR code is detected? :)
Thanks

This example present how to read QR code data with Webcam Capture library together with ZXing. Webcam Capture is compatible with both 32- and 64-bit Windows, Linux and Mac OX. For Linux it also supports ARM architecture.
The code is pretty simple:
Webcam webcam = Webcam.getDefault(); // non-default (e.g. USB) webcam can be used too
webcam.open();
Result result = null;
BufferedImage image = null;
if (webcam.isOpen()) {
if ((image = webcam.getImage()) == null) {
continue;
}
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
result = new MultiFormatReader().decode(bitmap);
} catch (NotFoundException e) {
// fall thru, it means there is no QR code in image
}
}
if (result != null) {
System.out.println("QR code data is: " + result.getText());
}

zxing has a port to Actionscript, which would make it usable via Flash, which can access a webcam. The port is a little old and not 100% complete, but ought to work.

You could use gstreamer in order to interact with your camera. For windows it could be gstreamer again or DirectShow. In both cases you will need to capture your data by using some special filters, in DirectShow it would be SampleGrabber. I think that gstreamer should provide some similar plugins.

Related

Anychart Android Java export chart as SVG or PNG in specific local folder

I was trying to create and save an image with AnyChart for an android application. This image is created without being rendered since the idea is to use the data from a vector to generate the image and save it on the phone's memory. I am using Java for programming the android application.
I have been testing the ".saveAsPng()" and ".saveAsSVG()" functions from the Anychart Library but there has been no success... I don't receive an error but I don't get the image either... and I don't know exactly how to proceed...
I tried to follow this guideline (https://docs.anychart.com/Common_Settings/Server-Side_Rendering) but as I said, I haven't succeeded in generating and saving the file.
This is the code that I have been using:
private class CustomDataEntry2 extends ValueDataEntry {
CustomDataEntry2(double x, Number value) {
super(x, value);
}
}
_
List<DataEntry> dataLateral = new ArrayList<>();
for (int p=0; p<DataX.size();p++) {
dataLateral.add(new CustomDataEntry2(DataY.get(p), DataX.get(p)));
}
AnyChartView anyChartViewLateral = new com.anychart.AnyChartView(this);
APIlib.getInstance().setActiveAnyChartView(anyChartViewLateral);
anyChartViewLateral.setProgressBar(new ProgressBar(this));
Polar polarLateralImage = AnyChart.polar();
polarLateralImage.startAngle(90);
Linear xScaleLateral = Linear.instantiate();
xScaleLateral.minimum(-180).maximum(180);
xScaleLateral.ticks().interval(90);
polarLateralImage.xScale(xScaleLateral);
Line polarSeriesLine = polarLateralImage.line(dataLateral);
polarSeriesLine.closed(false).markers(true);
polarSeriesLine.markers().size(3);
polarLateralImage.autoRedraw(true);
anyChartViewLateral.setChart(polarLateralImage);
polarLateralImage.saveAsPng(400,400,0.3,"testImage.png");
Could anyone tell me what am I missing or what amb I doing wrong? I know I might be asking too much, but if it were possible, I would be happy if someone could provide a code snippet that works.
Thank you very much!
Unfortunately, the current version of the AnyChart Android native library doesn't support exporting features, it was no implemented yet.

Get the latest image from IP Camera in Java

I'm working on Java APP that will process the stream from the IP Camera (Milesight MS-C2682-P) located on Local network. It will detect objects and trigger actions depending on what's in the image (let´s say it will start an alarm, when a person is detected) - for that I need it to be with minimal delay.
I have an RTSP link "rtsp://username:password#ip_addr:rtsp_port/main", to access stream from my IP Camera, but in my JAVA app there is a 12 seconds delay (and it's increasing). This happens, when images are not handled fast enough, so they are buffered. There are "hacks" and "workarounds" (OpenCV VideoCapture lag due to the capture buffer), but I believe there has to be a prettier solution.
The other link I was able to get is an HTTP one, that uses also H.264 codec (can be used with MJPEG and MPEG4, if there is a possible way to use them effectively). "http://username:password#ip_addr:http_port/ipcam/mjpeg.cgi" - works like a charm.. in Python and browser. However, it doesn´t work in Java, an error is thrown:
OpenCV(4.2.0) C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): HTTP_URL in function 'cv::icvExtractPattern'
Both links work smoothly in VLC.
So, the network is not a problem ('cause VLC handles stream with minimal delay) and Python using OpenCV is also doing a good job. It all comes down to Java implementation of OpenCV.. I guess.
Here is a Java code:
VideoPlayer videoPlayer = new VideoPlayer(); // My Class, just creates and updates JFrame, works like a charm with laptop's webcam, so certainly no issues here
Mat image = new Mat();
VideoCapture ipCamera = new VideoCapture(RTSP_URL);
// or the HTTP link
// VideoCapture ipCamera = new VideoCapture(HTTP_URL);
// verify if u got access to camera
if (!ipCamera.isOpened()) {
System.out.println("ERROR: Camera isn't working !!! ");
return;
}
System.out.println("OK: Connected to camera.");
while (true) {
ipCamera.read(image);
videoPlayer.updateVideo_MatImage(image);
}
And this is the Python code I'm using:
import cv2
cap = cv2.VideoCapture(RTSP_URL)
# or the HTTP link
# cap = cv2.VideoCapture(HTTP_URL)
while True:
ret, image = cap.read()
cv2.imshow("Test", image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
I just need to get the latest image, when a request is made. So I need to avoid any kind of buffering. It has to be implemented in Java since it's a requirement for this project.
So is there a way to get only latest image from camera?
What could cause the error mentioned above?
Thank you guys for any advice.

Video Transcode with Android MediaCodec

Struggling with Android MediaCodec, I'm looking for a straight forward process to change the resolution of a video file in Android.
For now I'm trying a single thread transcoding method that makes all the work step by step so I can understand it well, and at high level it looks as follows:
public void TranscodeVideo()
{
// Extract
MediaTrack[] tracks = ExtractTracks(InputPath);
// Decode
MediaTrack videoTrack = tracks.Where(o => o.IsVideo).FirstOrDefault();
MediaTrack rawVideoTrack = DecodeTrack(videoTrack);
// Edit?
// ResizeVideoTrack(rawVideoTrack);
// Encode
MediaFormat newFormat = MediaHelper.CreateVideoOutputFormat(videoTrack.Format);
MediaTrack encodeVideodTrack = EncodeTrack(rawVideoTrack , newFormat);
// Muxe
encodeVideodTrack.Index = videoTrack.Index;
tracks[Array.IndexOf(tracks, videoTrack)] = encodeVideodTrack;
MuxeTracks(OutputPath, tracks);
}
Extraction works fine, returning a track with audio only and a track with video only. Muxing works fine combining again two previous tracks. Decoding works but I don't know how to check it, the raw frames on the track weight much more than the originals so I assume that it's right.
Problem
The encoder input buffer size is smaller than the raw frames size, and also related to the encoding configured format, so I assume that I need to resize the frames in some way but I don't find anything useful. I'm correct on this? I'm missing something? What is the way to go resizing Raw video frames? Any help? :S
PD
Maybe you will notice that I'm using C# (Xamarin.Android) for more fun. But the underlaying API is of course Java.
I'm using ByteBuffers, not Surfaces because it seems easier. I will be the next step using surfaces, any advice is welcome.
I know that the single thread process is highly inefficient, but makes it simple. It will be another next step to connect the decoder output buffer to the encoder input buffer.
I digged through PhilLab, Grafika and Bigflake examples but nothing seems to be very useful for me.
Avoiding to use ffmpeg on Android.
Thank you everyone for your time.
Going off of the comment above to implement libVLC
Add this to your app root's build.gradle
allprojects {
repositories {
...
maven {
url 'https://jitpack.io'
}
}
}
Add this to your dependent app's build.gradle
dependancies {
...
implementation 'com.github.masterwok:libvlc-android-sdk:3.0.13'
}
Here is an example of loading an RTSP stream as an activity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_stream_layout);
// Get URL
this.rtspUrl = getIntent().getExtras().getString(RTSP_URL);
Log.d(TAG, "Playing back " + rtspUrl);
this.mSurface = findViewById(R.id.camera_surface);
this.holder = this.mSurface.getHolder();
ArrayList<String> options = new ArrayList<>();
options.add("-vvv"); // verbosity
//Add vlc transcoder options here
this.libvlc = new LibVLC(getApplicationContext(), options);
this.holder.setKeepScreenOn(true);
//this.holder.setFixedSize();
// Create media player
this.mMediaPlayer = new MediaPlayer(this.libvlc);
this.mMediaPlayer.setEventListener(this.mPlayerListener);
// Set up video output
final IVLCVout vout = this.mMediaPlayer.getVLCVout();
vout.setVideoView(this.mSurface);
//Set size of video to fit app screen
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
ViewGroup.LayoutParams videoParams = this.mSurface.getLayoutParams();
videoParams.width = displayMetrics.widthPixels;
videoParams.height = displayMetrics.heightPixels;
vout.setWindowSize(videoParams.width, videoParams.height);
vout.addCallback(this);
vout.attachViews();
final Media m = new Media(this.libvlc, Uri.parse(this.rtspUrl));
//Use this to add transcoder options m.addOption("vlc transcode options here");
this.mMediaPlayer.setMedia(m);
this.mMediaPlayer.play();
}
Here is the documentation of vlc transcoder options
https://wiki.videolan.org/Documentation:Streaming_HowTo_New/
You are right, the input buffer size of the encoder is smaller because it expects input to be of the specified dimensions. The encoder only, like the name suggests, encodes.
I read your question as more of a "why" than a "how" question so i'll only point you to where you'll find the "why's"
The decoded frame is a YUV image (is suggest to quickly skim through the wikipedia article), usually NV21 if i'm not mistaken but might be different from device to device. To do this i suggest you use a library as every every plane of the image needs to be scaled down differently and it usually takes care of filtering.Check out libYUV. If you are interested in the actual resizing algorithms check out this and for implementations this.
If you are not required to handle the decoding and encoding with bytebuffers, i suggest to use a surface as you already mentioned. It has multiple benefits over decoding to bytebuffers.
More memory efficient as there is no copy between the native buffer and app allocated buffer, the native buffers are simply geting swapped from and to the surface.
If you plan to render the frame, be it for resizing or displaying, it can be done by the devices graphic processor. On how to do that check out BigFlakes DecodeEditEncode test.
In hope this answers some of your questions.

Take Screenshot of Android screen and save to SD card

There are a few questions here on SO about capturing screenshots of an android application. However, I haven't found a solid solution on how to take a screenshot programatically using the android SDK or any other method.
So I thought I would ask this question again in the hopes that I can find a good solution, hopefully one that will allow capturing full length images that I can save to the SD card or somewhere similar.
I appreicate any help
This is not possible directly on the device/emulator, unless it is rooted.
to honest all I need it for is the emulator as this is for a testing application on a PC
This sounds like a job for monkeyrunner.
monkeyrunner tool can do the job for you with bit of adb command, [python script]
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
//waits for connection
device = MonkeyRunner.waitForConnection()
//take the current snapshot
device.takeSnapshot()
//stores the current snapshot in current dir in pc
device.writeToFile('current.png')\
//copy it to the sd card of device
os.subprocess.call('adb push current.png /sdcard/android/com.test.myapp/current.png')
Note: call this jython script file
monkeyrunner.bat <file name>
You will most likely not be happy with this answer, but the only ones that I have seen involve using native code, or executing native commands.
Edit:
I hadn't seen this one before. Have you tried it?:
http://code.google.com/p/android-screenshot-library/
Edit2: Checked that library, and it also is a bad solution. Requires that you start the service from a pc. So my initial answer still holds :)
Edit3: You should be able to save a view as an image by doing something similar to this. You might need to tweek it a bit so that you get the width/height of the view. (I'm inflating layouts, and specify the width/height when I layout the code)
View content = getView();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
File file = new File(pathAndFilename);
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 100, ostream);
ostream.close();
You can look at http://codaset.com/jens-riboe/droidatscreen/wiki (with a write up at http://blog.ribomation.com/2010/01/droidscreen/): this is a Java library that uses adb to capture a screen shots. I've been able to (with a lot of elbow grease) modify the source to let me automatically capture a timed series of screen shots (which I use for demo videos).
You can see the class structure at http://pastebin.com/hX5rQsSR
EDIT: You'd invoke it (after bundling all the requirements) like this:
java -cp DroidScreen.jar --adb "" --device "" --prefix "" --interval

What is the best way to handle photo uploads?

I'm doing a website for a family member's wedding. A feature they requested was a photo section where all the guests could go after the wedding and upload their snaps. I said this was a stellar idea and I went off to build it.
Well there's just the one problem: logistics. Upload speeds are slow and photos from modern cameras are huge (2-5+Megs).
I will only need ~800px wide images and some of them might require rotating so ideally I'm looking about using a client-side editor to do three things:
Let users pick multiple files
Let them rotate some images so they're the right way up
Resize them and then upload
And in my dream world, it'd be free and open source. Any ideas?
Just a reminder: this is something the guests have to use. Some of them will be pretty computer savvy but others will be almost completely illiterate. Installing desktop apps isn't really an option. And I assume 98% of them have Flash and Java installed.
Edit: I'd prefer a Flash/Java option over SilverLight, not least because it has a smaller install rate at the moment, but also because I'm on Linux and I'd like to test it =)
The most common solution for this is a java applet, although most of them are not free. Examples:
http://www.jumploader.com/
http://www.aurigma.com/Products/ImageUploader/OnlineDemo.aspx
http://www.javaatwork.com/java-upload-applet/details.html
JUpload, mentioned by ScArcher2
I have had good luck with Gallery. It is free, open source, and has all the features you mentioned.
It will allow your users to upload photos without any intervention from you.
Another option could be to allow people to upload their photos to whatever service they're used to using (flickr, google, smugmug, or any other), and just accept a username for that service, or a URL for the folder.
Then you can have your application grab a copy of those pictures to store locally with a consistent interface.
I've used swfupload quite a bit. It's pretty awesome: http://www.swfupload.org/
If you are doing this with Flash and using Flickr, then I would check out the AS3 Flickr library:
http://code.google.com/p/as3flickrlib/
which has support for uploading images.
Upload requires authentication. The library also contains a Flex based control for handling this:
http://www.mikechambers.com/blog/2008/08/12/flex-based-flickr-api-authorization-control/
(the rest of the library is ActionScript 3 and can be used in Flex or Flash.
Probably the easiest solution is to just have the images uploaded to Flickr, edited in Picnik (built into Flickr now), and then loaded onto the users site using either the Flickr RSS feeds or APIs:
http://www.flickr.com/help/picnik/
http://www.flickr.com/services/api/
hope that helps...
mike chambers
mesh#adobe.com
I'd use an applet. You could do the resizing of the pictures and rotating on the client side.
It looks like JUpload may do this for you.
Picasa is a pretty great/free photo management app. It let's you do some pretty impressive editing, and has upload capabilities, though I can't remember if it will upload to anywhere, or just certain popular sites (like Flickr).
You could use Silverlight or Flash or some custom plugin to allow managed uploads, where you can display a progress bar for example. There isn't much you can do about upload speeds but you can at least show them progress while it's going on.
I don't know of any canned upload programs you can use but it shouldn't be too hard to make one (unless you don't know Flash or Silverlight).
How about using PhotoShop Online It allows you to edit photos with a web based editor and offers 2GB of storage. I've not used it myself so don't know if it allows for multiple users to access the same account though
Out of curiosity, on what web stack is this to run? LAMP? 2k3+IIS? etc etc? Many of the open source solutions out there are cross-platform but others are not...
Is E-mailing the photo in an available option?
Most people who want to share photos probably already know how to send photos in email. And most email clients has already solved the problems of file uploading.
Just setup one gmail/whatevermail account and have your website poll the inbox.
It's something like what TwitPic does for twitter but your requirements seem to be more simpler than that.
Personally most users don't understand DPI and their images even trimmed down end up larger than the php.ini for most hosting companies allow.
I'm not sure how much control you want to give them or how you want the public side to behave.
I'd suggest using a dropbox FTP application such as http://etonica.com/dropbox/index.html (tango dropbox) It's free to your clients and you only have to pay for your version so you can set up the FTP information and secure it.
I'd have them download something link paint.net (which is FREE) have them edit the photos to the proper size and then just drag and drop them to this application. it's easy and doesn't require php.ini to be modified.
You could also use something like slideshowpro's director application.
I completly agree with zigdon, allow different sites, but only pick up photos from the web. I you still want to allow uploads, and put a cap on size.
Now, if you want to throw yourself into something big, I would suggest putting a cap on size, and then using JQuery (or other library) to work with the images.
Just my 2 cents
You could also have them email the pictures to picasa. Picasa web has a feature where you can send images to a "secret" email that will post them to a picasa account. Set up a picasa account, distribute the "secret" email, and wait for all the pictures to show up.
Going the Flickr route is easy and will work well.
If you want to go more advanced, I'd recommend snipshot or picknik (Flickr uses it). Both are free to use and have APIs to use.
I am currently required to implement the similar requirement as Oli.
I believe Facebook.com use java applet of some sort, and it work pretty well but I am not sure if the applet available as OSS. I am going to look into JUpload suggested by ScArcher2.
If you guy no of any other good applet please keep it coming.
I'd highly suggest using FileBrowser by Lussomo. It's as easy as 'drag and drop' :D
I've used it for my game development team where we had a raw dump of over 200 concept art images, and we simply extracted FileBrowser to a PHP-enabled webserver and dumped the images in appropriate directories (1 per album), and ran the thumbnailing script. It handles cropping of the images, and optimizing their size for you. So much better than using something like Menalto Gallery where you have to upload them through an awkward upload interface.
Try this out
http://www.lunarvis.com/products/tinymcefilebrowserwithupload.php
Depends on the web server. If you can use servlets, try this :
// UploadServlet.java : Proof of Concept - Mike Smith March 2006
// Accept a file from the client, assume it is an image, rescale it and save it to disk for later display
import javax.servlet.http.*;
import javax.imageio.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.*;
import org.apache.commons.fileupload.servlet.*;
import java.awt.image.*;
import java.awt.*;
public class UploadServlet extends HttpServlet {
public static void printHeader(PrintWriter pw) {
pw.println("<HEAD><TITLE>Upload Servlet</TITLE><HEAD>");
pw.println("<BODY>");
}
public static void printTrailer(PrintWriter pw) {
pw.println("<img src=\"../images/poweredby.png\" align=left>");
pw.println("<img src=\"../images/tomcat-power.gif\" align=right>");
pw.println("</BODY></HTML>");
}
public void init() { // Servlet init() : called when the servlet is LOADED (not when invoked)
}
public void service(HttpServletRequest req, HttpServletResponse res) throws IOException {
DiskFileItemFactory dfifact;
ServletFileUpload sfu;
java.util.List items;
Iterator it;
FileItem fi;
String field, filename, contype;
boolean inmem, ismulti;
long sz;
BufferedImage img;
int width, height, nwidth, nheight, pixels;
double scaling;
final int MAXPIXELS = 350 * 350;
res.setContentType("text/html");
PrintWriter pw = res.getWriter();
printHeader(pw);
ismulti = FileUpload.isMultipartContent(req);
if (ismulti) {
pw.println("Great! Multipart detected");
dfifact = new DiskFileItemFactory(999999, new File("/tmp"));
sfu = new ServletFileUpload(dfifact);
try {
items = sfu.parseRequest(req);
} catch (FileUploadException e) {
pw.println("Failed to parse file, error [" + e + "]");
printTrailer(pw);
pw.close();
return;
}
it = items.iterator();
while (it.hasNext()) {
fi = (FileItem) it.next();
if (fi.isFormField()) {
pw.println("Form field [" + fi.getFieldName() + "] value [" + fi.getString() + "]");
}
else { // Its an upload
field = fi.getFieldName();
filename = fi.getName();
contype = fi.getContentType();
inmem = fi.isInMemory();
sz = fi.getSize();
pw.println("Upload field=" + field + " file=" + filename + " content=" + contype + " inmem=" + inmem
+ " size=" + sz);
InputStream istream = fi.getInputStream();
img = ImageIO.read(istream);
nwidth = width = img.getWidth();
nheight = height = img.getHeight();
pixels = width * height;
if (pixels > MAXPIXELS) {
scaling = Math.sqrt((double) MAXPIXELS / (double) pixels);
nheight = (int) ((double) height * scaling);
nwidth = (int) ((double) width * scaling);
}
BufferedImage output = new BufferedImage(nwidth, nheight, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = output.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, nwidth, nheight, null);
ImageIO.write(output, "jpeg", new File("/var/tomcat/webapps/pioneer/demo.jpg"));
istream.close();
}
}
}
else
pw.println("Bugger! Multipart not detected");
printTrailer(pw);
pw.close();
}
public void destroy() {
}
}
GIMP (http://www.gimp.org/) is a good tool for doing resize and is open source.

Categories