Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Barcode question Type #2

Closed
benzea opened this issue Nov 23, 2012 · 34 comments
Milestone

Comments

@benzea
Copy link
Member

@benzea benzea commented Nov 23, 2012

This was an idea I had a while ago. One could add a barcode question type, which is simply a blank field that will be passed to zbar for analysis.

Usage Scenario:

  • Add field to identify the person that is filling out the questionnaire
  • Hand out the same questionnaire to everyone
  • Hand out Barcode Stickers separately to identify specific persons.
@ferdisdot

This comment has been minimized.

Copy link
Member

@ferdisdot ferdisdot commented Apr 8, 2013

Barcode fields may also be interesting to avoid some privacy issues.

One can use similar looking barcodes for each posibility. This makes it possible to provide answers in a not human readable way.
This may be interesting for e.g. medicinical surveys.

benzea pushed a commit that referenced this issue Oct 16, 2014
@thomasfedb

This comment has been minimized.

Copy link

@thomasfedb thomasfedb commented May 21, 2017

Would be very helpful for my purposes. We often attached patient stickers to forms, which include a barcode or QR code.

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented May 24, 2017

It is rather simple to implement. Basically just requires:

  • Subclass text fields
  • Create buddies (basically implement subclassed behaviour; override recognize to fill in text from barcode)
  • Making it usable from LaTeX in a nice way (this might be the ugliest part)
  • Adding the hook to the parser (trivial)
@benzea benzea added this to the 2.0 milestone Jan 19, 2019
benzea added a commit that referenced this issue Jan 26, 2019
This is similar to a textbox but designed to hold a QR code which is
reported as a string.

Addresses #2 in the main program.
@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Feb 17, 2019

So, now the question is, how to make this reasonable usable on the LaTeX side.

As I see it, it would be similar to a textbox in most cases.

So:

  • We generally need to generate a question per box; in the class, I could imagine generating a header and one or more textbox questions with codebox type boxes.
  • The box size doesn't make sense to be huge, i.e. a few cm wide is good enough.
  • We probably want some sort of (default) placeholder inside the box, any ideas? Maybe some generic QR code icon?

As a start, we could just add the low level support to generate these boxes, add an example, and then see how people want to use the feature.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Feb 19, 2019

Would it be explicit enough with something like this ?

text1788

But the problem is, I have no idea how to do it in latex. I did some research with
/tcolorbox,
tikz

https://tex.stackexchange.com/questions/251670/dotted-frame-around-the-text

But no solution for the moment

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Feb 20, 2019

We could do that too. I was thinking of leaving the black frame as is, but putting a "qr code" icon into it (which wouldn't be a valid qr code obviously).

Doing so should be relatively simple already with the things that sdapsbase provides.

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Feb 20, 2019

Dotted frame would actually also be easy. The frame is drawn using tikz/pgf, so there is a lot of things you can do.

benzea added a commit to sdaps/sdaps-class that referenced this issue Mar 31, 2019
@benzea benzea closed this in 6303c19 Mar 31, 2019
@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Mar 31, 2019

Alright, I merged some experimental support. I haven't actually tested this properly to be honest, so please shout at the slightest issue!

Example: https://sdaps.org/class-doc/customlayout.html#codeboxes

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Mar 31, 2019

Also, I would like to add some nice wrappers to make it more usable. I really need some feedback on how people use it to do so.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Mar 31, 2019

Hi, great stuff, i managed to test it with my tex editor but can't setup it with sdaps correctly,

It fails with :

"Error: Caught an Exception while parsing the SDAPS file. The current state is:
Questionnaire
1(Text) text {1}
0(Codebox ) 12.0 21.6 58.4 42.1"

I couln't find any clue in questionnaire.log

edit : it seems it may due to columns frame as it works when there is only one codebox alone in a tex

edit 2 : it works when the codebox is not the first item

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 1, 2019

Ah, yes. The reason is that the section numbering clashes with the question numbering. It will work fine if you simply put the question underneath the first section header.

Or, you can use \sdaps_classic_ensure_section: which will insert an invisible section with number 0.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 1, 2019

Ok thanks.

I went further and still some trouble. When doing sdaps recognize, i got :

File "/usr/local/lib/python3.7/site-packages/sdaps/recognize/buddies.py", line 915, in recognize
res = read_barcode(surface, matrix.mm_to_px(),
NameError: name 'read_barcode' is not defined

It seems that

from sdaps.utils.barcode import read_barcode

is missing in sdaps/recognize/buddies.py

When adding it i now have :

File "/usr/local/lib/python3.7/site-packages/sdaps/recognize/buddies.py", line 916, in recognize
res = read_barcode(surface, matrix.mm_to_px(),
AttributeError: 'cairo.Matrix' object has no attribute 'mm_to_px'

I'll try to find the solution !

edit 1 : i'm not really sure of what i'm doing but it goes on, i changed

    res = read_barcode(surface, matrix,
                       x, y, width, height,
                       "CODE128")

as i'm using 1D barcode

now i have :

File "/usr/local/lib/python3.7/site-packages/sdaps/model/questionnaire.py", line 42, in get_data
self.sheet.data[self.id] = getattr(data, clsname)(self)
AttributeError: module 'sdaps.model.data' has no attribute 'Codebox'

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 1, 2019

Hah, did I mention that I didn't properly test this ;-)

Let me cook up a fix

benzea added a commit that referenced this issue Apr 1, 2019
There was a call to mm_to_px() that is already hidden away behind the
property in question and needs to be dropped.

See issue #2
benzea added a commit that referenced this issue Apr 1, 2019
We do not have a Codebox specific object to store recognized data.
Instead, simply use the Textbox object for this purpose.

See issue #2
@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 1, 2019

Thanks! I merged the first fix (i.e. removing the mm_to_px()) and added another commit so that Codebox is stored using the same mechanism as Textbox.

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 1, 2019

I am not sure about CODE128 vs. QR. The easiest thing would probably be to simply accept any barcode type in there.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 3, 2019

Okay, it's working fine for me.

A few comments on this feature, I intend to use it for fast, fast, reliable and user-friendly medical data entry by surgeons and patients.
Our IT department intends to implement an integrated system for collecting data on electronic medical records, but does not realize that our job is not just to be in front of a computer and that patients do not respond to surveys on their quality of life after surgery unless they have time before their consultation.

I will now try to make barcode recognition independent of the type of barcode (our patient label barcode is Code39 and not 128.....)

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

proc = subprocess.Popen(['zbarimg', '-q', '-Sdisable', '-S%s.enable' % btype.lower(), tmp], stdout=subprocess.PIPE)

Is the relevant line. Simply removing '-Sdisable' and '-S%s.enable' parameters should enable all barcode types that zbar can handle. So, I guess what we could do is allow passing None and doing exactly that then.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 3, 2019

Ok i i'm trying some changes but i'm not really sure what i'm doing ...

If i remove '-Sdisable', '-S%s.enable' , something is missing :

File "/usr/local/lib/python3.7/site-packages/sdaps/utils/barcode.py", line 86
proc = subprocess.Popen(['zbarimg', '-q', % btype.lower(), tmp], stdout=subprocess.PIPE)
^
SyntaxError: invalid syntax

When removing :

'-Sdisable', '-S%s.enable' % btype.lower(),

File "/usr/local/lib/python3.7/site-packages/sdaps/utils/barcode.py", line 95, in scan
assert barcode.split(b':', 1)[0].replace(b'-', b'').lower() == btype.lower().encode('ascii')
AssertionError

Ok now some argument is missing for

assert barcode.split(b':', 1)[0].replace(b'-', b'').lower() == btype.lower().encode('ascii')

But it seems to be important ...

# Is the /dev/stdin sufficiently portable?
    proc = subprocess.Popen(['zbarimg', '-q', '-Sdisable', '-S%s.enable' % btype.lower(), tmp], stdout=subprocess.PIPE)
    stdout, stderr = proc.communicate()
    os.unlink(tmp)

    if proc.returncode == 4:
        return None

    assert(proc.returncode == 0)
    barcode = stdout.split(b'\n')[0]
    assert barcode.split(b':', 1)[0].replace(b'-', b'').lower() == btype.lower().encode('ascii')


    # The following can be used to look at the images
    #rgb_surface.write_to_png("/tmp/barcode-%03i.png" % barcode)
    #barcode += 1

    return barcode.split(b':', 1)[1].decode('utf-8')
@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

Hehe, looks like you are not used to python :)

It really is '-S%s.enable' % btype.lower() which results in e.g. -Scode128.enable. I simply didn't bother to also copy the definition of what replaces %s.

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

Ah, right. Yes, you'll also need to disable the assertion. It simply double-checks that the found barcode has the expected type.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 3, 2019

Hehe sure, i'm only at the beginning with python !

Thanks for your help !

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 3, 2019

Ok great it works now with :

code39, code 128 etc thanks to some removing

as i made a lot of modification, i made a new clean sdaps installation from github,

it is still missing

from sdaps.utils.barcode import read_barcode

in buddies.py

but know i still have a problem : i can only read copied barcode and not scanned barcode, maybe because of the definition une tex ?

\ExplSyntaxOn
\let\myquestionbegin\sdaps_qobject_begin:nnn
\let\mytexthbox\sdaps_textbox_hbox:nnn
\let\myquestionend\sdaps_qobject_end:n
\let\mysettextboxtype\sdaps_textbox_set_type:n
% Set a global overlay with a nice icon (quite likely, you will just want
% to place text into the hbox below rather than just placing spacing).
\sdaps_context_set:n {
codebox = {
centered_text = {etiquette
% \begin{tikzpicture}[yscale=-0.1, xscale=0.1]
% \path[draw=black,fill=black,stroke=] (-1,0)
% -- (-1,5) -- (4,5) -- (4,0) -- cycle(7,0) -- (7,5) -- (12,5) -- (12,0) -- cycle(0,1) -- (3,1) -- (3,4)
% -- (0,4) -- cycle(8,1) -- (11,1) -- (11,4) -- (8,4) -- cycle(1,2) -- (1,3) -- (2,3) -- (2,2) -- cycle(5,2) --
% (5,3) -- (6,3) -- (6,2) -- cycle(9,2) -- (9,3) -- (10,3) -- (10,2) -- cycle(5,4) -- (5,6) -- (2,6) -- (2,7)
% -- (6,7) -- (6,4) -- cycle(0,6) -- (0,7) -- (1,7) -- (1,6) -- cycle(7,6) -- (7,7) -- (8,7) -- (8,6) --
% cycle(-1,8) -- (-1,13) -- (4,13) -- (4,8) -- cycle(5,8) -- (5,13) -- (6,13) -- (6,8) -- cycle(7,8) -- (7,9)
% -- (8,9) -- (8,10) -- (7,10) -- (7,13) -- (8,13) -- (8,11) -- (9,11) -- (9,10) -- (10,10) -- (10,9) -- (9,9)
% -- (9,8) -- cycle(10,9) -- (12,9) -- (12,8) -- (10,8) -- cycle(0,9) -- (3,9) -- (3,12) -- (0,12) --
% cycle(1,10) -- (1,11) -- (2,11) -- (2,10) -- cycle(11,10) -- (11,11) -- (12,11) -- (12,10) -- cycle(11,11) --
% (10,11) -- (10,12) -- (9,12) -- (9,13) -- (12,13) -- (12,12) -- (11,12) -- cycle;
% \end{tikzpicture}
},
}
}
\ExplSyntaxOff

%\textbox{0cm}{}
\myquestionbegin{barcode}{text}{text}
\mysettextboxtype{codebox}

% Note that we use hspace + vrule for sizing here, that is a bit weird but
% a reasonable method of setting a size
\mytexthbox{}{1bp}{ \hspace{5.6cm} \vrule width 0pt height 3.3cm depth 0cm }
\myquestionend{barcode}

i changed heigh and depth in order to fit the document

benzea added a commit that referenced this issue Apr 3, 2019
@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 3, 2019

I have some new facts. When I want to scan with an added patient label: failure. When I add a barcode in copy and paste on a clean stamp.pdf file: it works. Also when I print this file and then scan it again: sdaps recognizes the barcode.

Is this due to a matrix problem? Between the entire questionnaire matrix and the codebox matrix?

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

Could you check that the barcode from the first file looks reasonable (in the .tif file in the project or UI)? Maybe the scan is just bad or low quality for some reason?

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 3, 2019

The barcode looks good, there is some text before the barcode on the patient label, i tried to erase it after scan but doesn't works. When i try online barcode detector it works, and the same for bottom ones.

I'll try to magnify the barcode size

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

Nah. More likely something else is going wrong. Like e.g. the matrix being applied in the wrong way or I made a horrible mistake and we are looking at the wrong area.

Two things you can do:

  1. Run sdaps annotate and check that the area is correct (I am going to have a look at the code now)
  2. Look at barcode.py there is a comment at the bottom, if you enable those two lines you can check whether the cut out area is sane on that side.
@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

Hmm, 1. looks entirely correct (by the way, I am amazed you are actually using the whole override/overlay stuff …).

Oh, and 2. is missing quite a lot of code …

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

This should fix the barcode image writing stuff:
show-images.patch.txt

(I will never understand why github doesn't like .patch …)

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 3, 2019

But, AFAICT, everything is working as expected. So maybe it is some other issue, possibly even that the barcode is destroyed by the import or so?

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 4, 2019

I have one success and one fail for the same document but with some rotation of the label.

pictures of the barcode are well recorded in the /tmp, and the rotated one is also still rotated.

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 4, 2019

Do you think the rotation is the issue?

The image is not being de-skewed for barcode recognition. I always assumed that this would actually decrease the quality rather than improve it.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Apr 4, 2019

I have done a LOT of label sticking / scanning / barcode recognition today, and it only works when the barcode is horizontal.

The thing is, it works:) I am very happy but maybe for some cases it will not recognize if the label is not pasted with surgical precision :)

@benzea

This comment has been minimized.

Copy link
Member Author

@benzea benzea commented Apr 5, 2019

OK, no idea about that unfortunately. I guess zbar is not very robust with regard to rotation then; but I am not sure whether that means we should add workarounds or something into SDAPS …

If this is an issue, we would need to a collection of samples that one can test the barcode recognition against.

@jdanion

This comment has been minimized.

Copy link

@jdanion jdanion commented Aug 5, 2019

Another idea that would need some help as i can't find where to implement it :

Where should i add some code to extract the image of a codebox like csv export --images.

Is adding

"image_writer = self.obj.question.questionnaire.csvdata.image_writer"

somewhere a good start ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.