Project

General

Profile

Feature #144

BARCODE changes

Added by Michele Vivoda about 6 years ago. Updated about 6 years ago.

Status:
Assigned
Priority:
medium
Assignee:
-
Category:
-
Target version:
-
Start date:
2012-05-10
Due date:
% Done:

0%

Estimated time:

Description

This patch I am describing here started as a setup step for introducing the barcode,
mainly implement parameters for each translation (pdf) but finished in the complete
barcode implementation changes. Is difficult to make step by step such big change.

The tests are all ok, I a drastic change but I am confident it will work.

Note/Question: I am making a multi module patch since modules involved are multiple,
but I don't know how to put it together since there
are different repositiories involved, maybe just take them all..
I marked the pull requests that must be committed together (in different modules) with BARCODE

Changes for sqs-translator:

1) To start I simplified the Translator interface to be simpler:
The Translator interface has been changed to have only the methods

void translate(TranslatorSource source, OutputStream)
InputStream translate(TranslatorSource source)

The other methods have been left there but commented out,
the commented out implementations in AbstractTranslator now all use
a TranslatorSource to call their overloaded counterpart,
where possible the implementation methods have been made final.
I commented out for test, to be sure all the components where calling
the new methods to propagate resolver and parameters to all translators.
If you like I can re put the previous overloaded methods there,
but I think that a thinner interface is perhaps better.

The aim was to get to a point in which the main implementation
method (execute) does not declare many parameters
but only one "context" object including input, output, resolver and xslt parameters,

I did this because:
A) I had to modify methods in any case for adding xslt-parameters per print
B) if one day one need to add one new configuration
parameter, say "encoding", to the context simply will add a method to the "context"
class and won't have to change method declarations in all implementations
of Translator.

2) I changed the method of FOPTranslator#translate() to translateFO() since
is specific of FO, to not get confused with the translate() methods of Translator

3) I changed the convert3.xsl to add some little functionalities for images. in a previous commit
4) I fixed the calculation of suffixes for config as per Defect # 142

5) I changed some code to make Sqs2PDFTranslator more friendly, before
the minimal constructor parameters were [fopURL, xsltURL, pageSetting, URIResolver,filename]
now they are only [filename]. made test SQSToPDFTranslatorAPITest for this,
the aim is to have a class that is simple and ready to use,
to attract potential developers/users that now do not need to "know" much to start.

I am not sure about the groupId, appID and filename params though, could you tell me something?

6) I added the barcode code to all xslt involved

Barcode Prints! You may see in the tests (at the moment tests show in PDF reader the pdf, will remove)

Other components
----------------
Other components have little changes that must however be committed together to compile.

sqs-editor: changed ExportFileLogic to use the new TranslateSourceBean class
sqs-reader: changed PDFBookmarkFormMasterFactory, PDFBookmarkToSQMTranslator,PDFtoBookmarkTranslator to use the new source class.

End

---------------Down is a draft

Ideas For Translator (These are not really needed however, performance is super ok)
- Maybe use TemplatesHandler for better multi threading
- wondering how could be the performance using DOM (caching the tree, not only the bytes),
Scenario: load a translator with uri-resolver and a sqs-source (that is kept as DOM)
and then call for each printed document a transform method that receives
an output (stream) and parameters.

Associated revisions

History

#1 Updated by Hiroya Kubo about 6 years ago

First of all, Michele, I must thank you for all the kind you are contributing to the SQS project.

Michele Vivoda wrote:

This patch I am describing here started as a setup step for introducing the barcode,
mainly implement parameters for each translation (pdf) but finished in the complete
barcode implementation changes. Is difficult to make step by step such big change.

The tests are all ok, I a drastic change but I am confident it will work.

Sounds very nice. Go ahead with your story.

Note/Question: I am making a multi module patch since modules involved are multiple,
but I don't know how to put it together since there
are different repositiories involved, maybe just take them all..
I marked the pull requests that must be committed together (in different modules) with BARCODE

You may send me a set of pull requests on each repositories. We will be able to manage the changes.

Changes for sqs-translator:

1) To start I simplified the Translator interface to be simpler:
The Translator interface has been changed to have only the methods

void translate(TranslatorSource source, OutputStream)
InputStream translate(TranslatorSource source)

The other methods have been left there but commented out,
the commented out implementations in AbstractTranslator now all use
a TranslatorSource to call their overloaded counterpart,
where possible the implementation methods have been made final.
I commented out for test, to be sure all the components where calling
the new methods to propagate resolver and parameters to all translators.
If you like I can re put the previous overloaded methods there,
but I think that a thinner interface is perhaps better.

The aim was to get to a point in which the main implementation
method (execute) does not declare many parameters
but only one "context" object including input, output, resolver and xslt parameters,

I did this because:
A) I had to modify methods in any case for adding xslt-parameters per print
B) if one day one need to add one new configuration
parameter, say "encoding", to the context simply will add a method to the "context"
class and won't have to change method declarations in all implementations
of Translator.

I welcome your change! The new interface seems better to understand how to use it.

2) I changed the method of FOPTranslator#translate() to translateFO() since
is specific of FO, to not get confused with the translate() methods of Translator

3) I changed the convert3.xsl to add some little functionalities for images. in a previous commit
4) I fixed the calculation of suffixes for config as per Defect # 142

OK.

5) I changed some code to make Sqs2PDFTranslator more friendly, before
the minimal constructor parameters were [fopURL, xsltURL, pageSetting, URIResolver,filename]
now they are only [filename]. made test SQSToPDFTranslatorAPITest for this,
the aim is to have a class that is simple and ready to use,
to attract potential developers/users that now do not need to "know" much to start.

OK, go ahead.

I am not sure about the groupId, appID and filename params though, could you tell me something?

The params are legacy and not used now. I think I shall remove them on this occasion.

6) I added the barcode code to all xslt involved

Barcode Prints! You may see in the tests (at the moment tests show in PDF reader the pdf, will remove)

Excellent!

Other components
----------------
Other components have little changes that must however be committed together to compile.

sqs-editor: changed ExportFileLogic to use the new TranslateSourceBean class

I modified ExportFileLogic by myself to follow up your changes.

sqs-reader: changed PDFBookmarkFormMasterFactory, PDFBookmarkToSQMTranslator,PDFtoBookmarkTranslator to use the new source class.

OK, I have merged it.

---------------Down is a draft

Ideas For Translator (These are not really needed however, performance is super ok)
- Maybe use TemplatesHandler for better multi threading
- wondering how could be the performance using DOM (caching the tree, not only the bytes),
Scenario: load a translator with uri-resolver and a sqs-source (that is kept as DOM)
and then call for each printed document a transform method that receives
an output (stream) and parameters.

Very interesting suggestions. Using DOMSource instead of StreamSource will be better...

#2 Updated by Michele Vivoda about 6 years ago

Hi Hiroya,
you are welcome, my pleasure, happy that you liked the modifications.

So did you manag to merge also the changes of sqs-translator ?

#3 Updated by Hiroya Kubo about 6 years ago

Michele Vivoda wrote:

So did you manag to merge also the changes of sqs-translator ?

Yes, I did. I only made some minor fixes on SQSToPDFTranslatorCore.java to externalize japanese characters into a resource file.

#4 Updated by Michele Vivoda about 6 years ago

Yes, I saw something was lost in encoding ;-)

I forked again sqs-util and translator and they are working, very good!

Now I think more or less all the changes I made in my previous personal version have been copied to the main current version. I will re-deploy the publishing web application with this new version to check everything is ok.

I would like to document a little how the barcode works and may be how to use the translator, which format do you use for the wiki ? Html is ok ?

The next step will be recognition of barcode in sqs-reader.

Have you read in the log about the idea that barcodes can be used as an identifier for the questionay, for the page and for checking if the image is rotated ? I read that sorting papers is a difficult task and that some products evidentiate that they are able to read pages in any order and rotation. At the moment barcodes are used only as inputs,
but my idea is to use them also as "identifier" (that would be an internal detail of sqs).

#5 Updated by Hiroya Kubo about 6 years ago

Michele Vivoda wrote:

I forked again sqs-util and translator and they are working, very good!

:-)

Now I think more or less all the changes I made in my previous personal version have been copied to the main current version. I will re-deploy the publishing web application with this new version to check everything is ok.

Good luck!

I would like to document a little how the barcode works and may be how to use the translator, which format do you use for the wiki ? Html is ok ?

We can use textile format. I made a small effort to add markdown support by installing a plugin to redmine, however, I failed to install because the plugin was too old to use.

You can use HTML though not quite satisfactorily. cf. http://www.redmine.org/boards/2/topics/17443
If you want to use HTML, please tell me the ALLOWED_TAGS.

The next step will be recognition of barcode in sqs-reader.

Have you read in the log about the idea that barcodes can be used as an identifier for the questionay, for the page and for checking if the image is rotated ?

Yes, It was delightful to read the log! I also planned to use barcodes to identify questionnaire masters and pages, but I have not stated yet.
The feature of validating page rotation has been already implemented. Please check class net.sqs2.omr.ap.deskew.PageUpsideDownValidator.

I read that sorting papers is a difficult task and that some products evidentiate that they are able to read pages in any order and rotation. At the moment barcodes are used only as inputs,
but my idea is to use them also as "identifier" (that would be an internal detail of sqs).

I agree with your idea.

In the current implementation of sqs-reader, a processing page index is calculated by (fileIndexInDirectory % numPagesOfThisQuestionnaire) and it is used as prereqisite for an OMRPageTask.
We will have to change this to overwrite a page index by a result of barcode reading.

#6 Updated by Michele Vivoda about 6 years ago

In the current implementation of sqs-reader, a processing page index is calculated by (fileIndexInDirectory % numPagesOfThisQuestionnaire) and it is used as prereqisite for an OMRPageTask. We will have to change this to overwrite a page index by a result of barcode reading.

So in a 2 pages questionary you should order files page 1,2,1,2 etc. right ?

About order I thought could be something different than files order, for example a list sorted alphabetically..

I was thinking of a preprocessing stage in which questionary scanned images are
1. checked for barcode and page
2. rotated if needed and
3. optionally, at the end, the file is renamed with the name of the identifier (so that also is not possible to have duplicates), name may include page

#7 Updated by Hiroya Kubo about 6 years ago

So in a 2 pages questionary you should order files page 1,2,1,2 etc. right ?

Right.

About order I thought could be something different than files order, for example a list sorted alphabetically..

Yes, to be exact, we can choose arbitrary order of PageID list in SessionSource instance.

You can find the code in net.sqs2.omr.session.init.SessionSourceInitializer.
It reads list of directory entries and sorted by filename in alphabetical order, and optionally sorted by multiple internal page index (multi page tiff) in numerical order, and then creates sorted list of PageID objects.

The list of PageID objects are kept in hierarchical SourceDirectory objects
The hierarchical SourceDirectory objects are kept in a SessionSource object.

I was thinking of a preprocessing stage in which questionary scanned images are
1. checked for barcode and page
2. rotated if needed and
3. optionally, at the end, the file is renamed with the name of the identifier (so that also is not possible to have duplicates), name may include page

I'm afraid renaming original files may cause troubles.

Let me describe my idea to use "virtual" PageIDs which are extracted from barcode contents.

The sequence of processing in MarkReaderSession:

1. read directory entries hierarchically and make a tree of lists of image files.
2. choose image files to be processed by checking its filename(if it is unknown) and timestamp(if it is newer) and make PageTask objects with it.
3. PageTask objects are queued in MarkReaderSession.
4. the PageTask objects are leased to PageTask executor daemons over RMI.
5. the one of PageTask executor daemons remotely retrieves a PageTask and its related data: the byte array of the image file and so on.
6. the PageTask executor daemon processes the PageTask(OMR).
5. the PageTask executor daemon returns a PageTask including its result to MarkReaderSession.

The stage 6 will be modified to check if the image contains barcode or not, then extract information of VirtualPageID, then create the copied PageTask with the VirtualPageID.
The original PageTask will be setup to afford the reference to the new PageTask with use of VirtualPageID.
The newly created PageTask can be processed on the same PageTask executor daemon with reusing in-memory-cached byte array of the image file.

#8 Updated by Michele Vivoda about 6 years ago

Yes, to be exact, we can choose arbitrary order of PageID list in SessionSource instance.

exactly what I meant but well said ;-)

I'm afraid renaming original files may cause troubles.

I mean renaming before starting the usual process of the reader, is transparent to it.
Imagine this scenario:
One votation for something, each questionary is personal and has an unique id.
4 scans must be made to be sure of the results (is a very important votation)

I take all the phisical papers in any order and I make a scan of all the questionaries in any order prepraing a list of images. I make this 4 times with same physical papers but presumably in different order and save the results in 4 sibling folders scan1, scan2, scan3, scan4. At this point the same questionary may be in folder [scan1] with name scan001.png and in folder [scan2] with name scan0334.png

Then I run the preprocess stage that reads the barcode, rotates if needed and renames the files with the barcode value.

At this point I have 4 dirs with the questionaries with same names, I think this organization of data is much more significant than the same data with the name of the scanned image that means nothing. For example at this stage one can see if a specific questionary has been scanned in all 4 scans, not possible before. One may fix also the (very extreme I admit, but with 2 scan only not so much) case of a page of a questionary that has been scanned only in one scan and a page of the same questionary scanned only in an other scan.

So I was thinking to a two-steps process, of course the first one can be made optional and work be made as is now for simpler use cases.

Now I go on reading the rest of your answer while browsing code.

#9 Updated by Michele Vivoda about 6 years ago

BTW Looks like normal scanners devices easily "jump" one or even two pages every ~100 when doing a pile of scans..they take more pages together... this is the reason of all these checks.

#10 Updated by Michele Vivoda about 6 years ago

Reading your answer more in detail, at first glance I would say your process is compatible with mine,
that the preprocessing is orthogonal to the parsing:
- Preprocessing is done before ;-) and just prepares the images that will be read by the sqs-reader
- Sqs-reader can work in any case with or without preprocessing
- Having the list of the files ordered by name-identifier is not a problem for reader (he won't count on it as now)
- Reading barcode is very fast and can be done 2 times, in preprocessing and in sqs-reader.

The main difference I think is that preprocessing can be made with human supervision, to fix some (hopefully little) problems that cannot be fixed by the reader (better, it would have to know too many things to do it)

Imagine the case of a 2 pages questionary. One of these pages is missing in one scan, the operator may scan again that page or use the same image of an other scan, in this way the sqs-reader results will be comparable. If this is not done before then you get one with "page missing" error and you probably cannot compare the values in the page that is present in both scans.

In the same way I think also to a sort of post-processing of sqs-results (that BTW I already had to implement in a swing app) that takes the results of the 4 different scans and finds those that have not the same result for all 4 scans. At this point the operator can see the 4 scans and the 4 results, possibly modifies one and approves one that is then marked as "human verified".

#11 Updated by Hiroya Kubo about 6 years ago

OK, we shall follow the KISS principal ( http://en.wikipedia.org/wiki/KISS_principle ).
Separating pre-process and post-process from sqs-reader will be a good design choice.

I also agree with the importance of "human verification" for scanned images. Go ahead!

BTW, the current sqs-reader itself can detect a part of invalid page sequence in scanned images with very simple algorithm.
sqs-reader/src/main/java/net/sqs2/omr/app/deskew/PageSequenceValidator.java

Also available in: Atom PDF