view all posts by Greg Lehey

Still more panorama processing

Greg Lehey Posted by Greg Lehey | Sun, 03 Jun 2012
see the original posting from Greg's diary

Into the office this morning, and my big panorama had been stitched, all 1 GB of it:

-rw-r--r--  1 grog  lemis  1078003761 Jun  3 00:56 X00-82.tif

Only later did I discover the errors:

This should be verandah-centre-equirectangular.jpeg.  Is it missing? This should be verandah-centre-detail.jpeg.  Is it missing?

Where did those stripes come from? They roughly coincide with the layers I took, but I haven't had problems like that before. But I didn't have time to look at it now; I'll revisit it later when the rest is done.

The next step was to run SaladoConverter. It started, flashed an error message and then closed the window. Repeatedly. What's the issue there? It took me a while to realize that the window isn't really intended to be looked at. To see what happens, you have to click on the File button and then select Show Log. And there was plenty to see, conveniently hidden by a tiny, not wide enough and certainly not high enough, and of course not resizeable window:

This should be java-error.gif.  Is it missing?

Fortunately you can cut and paste it (it wouldn't do to tell you the location of the log file, would it?), and there are several instances of this mess:

Processing image: /Photos/forsalad/verandah-centre.jpeg
Error: One factory fails for the operation "jpeg"
Occurs in: javax.media.jai.ThreadSafeOperationRegistry
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at com.sun.media.jai.opimage.StreamRIF.create(StreamRIF.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
at javax.media.jai.RenderedOp.getMinX(RenderedOp.java:2161)
at javax.media.jai.iterator.RectIterFactory.create(RectIterFactory.java:64)
at equirectangulartocubic.ImageBuffer.<init>(ImageBuffer.java:39)
at equirectangulartocubic.EquirectangularToCubic.processImageFile(EquirectangularToCubic.java:268)
at equirectangulartocubic.EquirectangularToCubic.main(EquirectangularToCubic.java:155)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.panozona.converter.utils.ComponentInvoker.invokeClass(ComponentInvoker.java:71)
at com.panozona.converter.utils.ComponentInvoker.run(ComponentInvoker.java:33)
at com.panozona.converter.utils.TasksExecutor.doInBackground(TasksExecutor.java:68)
at com.panozona.converter.utils.TasksExecutor.doInBackground(TasksExecutor.java:18)
at org.jdesktop.swingworker.SwingWorker$1.call(Unknown Source)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at org.jdesktop.swingworker.SwingWorker.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.awt.image.DataBufferInt.<init>(DataBufferInt.java:41)
at java.awt.image.Raster.createPackedRaster(Raster.java:458)
at sun.awt.image.codec.JPEGImageDecoderImpl.allocateDataBuffer(JPEGImageDecoderImpl.java:334)
at sun.awt.image.codec.JPEGImageDecoderImpl.readJPEGStream(Native Method)
at sun.awt.image.codec.JPEGImageDecoderImpl.decodeAsBufferedImage(JPEGImageDecoderImpl.java:210)
at com.sun.media.jai.codecimpl.JPEGImage.<init>(JPEGImageDecoder.java:110)
at com.sun.media.jai.codecimpl.JPEGImageDecoder.decodeAsRenderedImage(JPEGImageDecoder.java:46)
at com.sun.media.jai.opimage.CodecRIFUtil.create(CodecRIFUtil.java:112)
at com.sun.media.jai.opimage.JPEGRIF.create(JPEGRIF.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at com.sun.media.jai.opimage.StreamRIF.create(StreamRIF.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
at javax.media.jai.RenderedOp.getMinX(RenderedOp.java:2161)
at javax.media.jai.iterator.RectIterFactory.create(RectIterFactory.java:64)
at equirectangulartocubic.ImageBuffer.<init>(ImageBuffer.java:39)
at equirectangulartocubic.EquirectangularToCubic.processImageFile(EquirectangularToCubic.java:268)

What a mess! And what's a factory? Anyway, these 76 lines of internals (stack trace?) are SaladoConverter's (or maybe Java's) way of saying Not enough memory. Did a bit of experimentation and discovered that the settings specified a limit of 1 GB of memory. Tried again with 2 GB, still with no success. I was doing this on braindeath, a Microsoft XP machine, which only has 2 GB of memory, and that was because SaladoConverter causes Java to crash on dereel, my main machine. But defake has newer software, so tried it there, and it worked! Well, it crashed in the same way it did on braindeath, but that was a separate issue.

Tried increasing memory furtherdefake has 3 GB of memoryand then it occurred to me that what I'm using here is virtual memory, not real. On dereel, a 32 bit machine, the address space is limited to 3 GB, so increasing virtual memory beyond that just doesn't work, but defake is 64 bits, so I set the limit to 8 GB, and it ran. Here are the panoramas. And looking down from the dam panorama is surprisingly realistic:

This should be dam-downwards.jpeg.  Is it missing?

Next came the second conversion of the verandah panorama. The first one had run for nearly 7 hours, and just by chance I saw a discussion on the Hugin mailing list about the topic, in which Cartola suggested using multiblend, something I hadn't heard of, and which is supposed to be much faster. So I went looking for it, and surprise! It was relatively easy to build (once I added a Makefile, something the author hadn't thought necessary). Tried running it:

multiblend v0.4 (c) 2012 David Horman          http://horman.net/multiblend/
----------------------------------------------------------------------------

loading 00-820000.tif...
...
loading 00-820024.tif...
couldn't malloc iamge channel (2)

And yes, the spelling is original. This was after less than 2 minutes. enblend would have required a couple of hours to get to the same point, but it didn't run into memory problems. It looks as if multiblend gets some of its speed from using much more memory. Still, now I have more memory on defake, so I tried it there. It reached 8 GB virtual memory size before I stopped looking, but it was finished in 27 minutes. Unfortunately, the results weren't as good. Ran enblend on defake, which also grew surprisingly big, but finished in 5.8 hours. The results were worth it, though. Here first from multiblend and then from enblend. The results are more obvious when enlarged:

This should be verandah-centre-multiblend.jpeg.  Is it missing? This should be verandah-centre.jpeg.  Is it missing?
This should be verandah-centre-multiblend-detail.jpeg.  Is it missing? This should be verandah-centre-detail-2.jpeg.  Is it missing?

These two images were really stitched from exactly the same components. The blending at bottom right is very poor with multiblend, and interestingly some of the leaves appear to have moved left of centre. Clearly they have been chosen from other component images.

So: three days messing with this stuff, and I'm still not finished. I'll tidy up tomorrow, hopefully.


see the original posting from Greg's diary

Back to top