Audiveris / audiveris

Latest generation of Audiveris OMR engine
https://audiveris.github.io/audiveris
GNU Affero General Public License v3.0
1.58k stars 232 forks source link

java.lang.NegativeArraySizeException: -19035 on score from IMSLP220542 #531

Open hmmueller opened 2 years ago

hmmueller commented 2 years ago

Not finding a clef on the 8th staff on page 1; and the 11th staff on page 3 leads to these exceptions, which abort the OMR process. I tried playing around with a few options with "clef" in their name - but actually, I have no clue what to do ... I also don't see any "spurious glyphs" that might lead to a problem.

(The score is definitely of a bad quality, so I understand that Audiveris does not like it; however 4 of the 6 pages where "more or less" OMRed, with - for me - useful results).

Here are all files as a ZIP - pdf, omr, log: IMSLP220542.zip

H.M.

PeterGreth commented 2 years ago

Sooo... Just for fun I tried to debug this. 😄

  1. The following line clusters are calculated. Notice how the smallClustersRetriever found several clusters on the same y-level: image
  2. This causes there to be 9 systems: image
  3. When trying to recognize the clef in the red system, ClefBuilder::getOuterRect tries not to put the outerRect in the rectangle for the following ("below") system, here blue (purple parts are overlapping with red), and moves the yMax upwards accordingly
  4. Unfortunately, yMax then is smaller than yMin, leading to a negative rectangle height causing the NegativeArraySizeException at a later point

At this point I'm out because I don't know exactly where the mistake happened. Are the calculated line clusters (first image) okay or are they wrong already? I'm certain @hbitteur could give us an insight 😉

hbitteur commented 2 years ago

Yes, Audiveris had problems with staff 7 and staff 10, clusters of staff lines separated by poor line portions did not get merged properly. Subsequent processing failed of course.

So, we now have to investigate why the clusters merge failed. Stay tuned...

hbitteur commented 2 years ago

The problem is that there are almost no line segments on staff 7 to derive lines from. In this case, we have an easy workaround I just tried with success. In Tools | Options, navigate to LinesRetriever unit and then modify the value of minRunLength constant. This constant defines, in fraction of interline, the minimum length of horizontal runs to be considered for lines retrieval. By default, its value is 1.0, which for this sheet with interline value of 19 pixels, requires a minimum of 19 consecutive pixels for a run. I tried value 0.25 instead, which lowers the required length to 19/4 = 4.8 rounded to 5 pixels. And bingo, all your lines and thus staves and systems now get correctly recognized.

hbitteur commented 2 years ago

I don't know if we should keep this rather small run length value. The risk is of course to get a lot of false candidates for line portions. In the sheet at hand, these small staves are:

In this case, it was obviously a good choice.

hbitteur commented 2 years ago

With default 1.0 interline fraction, we have these filaments (on staff 7): image Which resulted in:

Systems: #1[1, 2, 3] #2[4, 5, 6] #3[7] #4[8] #5[9] #6[10] #7[11, 12] #8[13] #9[14, 15]

With 0.25 interline fraction, we now get these filaments (on the same staff 7): image And as result:

Systems: #1[1, 2, 3] #2[4, 5, 6] #3[7, 8, 9] #4[10, 11, 12]

These snapshots explain the result.

maximumspatium commented 2 years ago

IMSLP is full of low quality, low resolution scans especially if they were made from older (last century) editions like the said sheet. People still can read them because the human brain reconstructs the missing information on the fly. But a computer algorithm working on the pixel level will likely have troubles processing such a fragmented staff. Adjusting some parameters manually may help in several cases but it's difficult to come up with a generalized solution.

The best solution is to re-scan the score with a higher resolution.

hmmueller commented 2 years ago

Yes, of course.

However, such exceptions drop the complete result, even if parts of later pages might be useful for faster recreation of a score. So, in my opinion, a useful goal for Audiveris would be "survive (almost) any score; but recognize only what's sufficiently clear". What (e.g.) I then proceed to do with the recognized snippets - without, and with, errors -, is then another question.

Re parameter adjustment, for an occasional user (again, like me), it's hopeless to know which parameters to modify and how. But this is a separate (usability) problem, and might actually be solved - or improved - by examples like hbitteurs, where I learned about minRunLength.

Harald M.

hbitteur commented 2 years ago

In Audiveris code, there is (I'd better say: should be) no technical constant hard-coded in the algorithms. Instead, these values are handled by so-called Constant entities all around the Java classes, and each of these "constants" can be manually modified without the need to recompile the application.

A good example from the score at hand is this minimum length for a staff line candidate segment. A reasonable minimum length was set at 1.0 times the main interline value, rather arbitrarily but based on concrete input scores. In the score at hand we had a staff with low quality (read: many missing pixels) and crowded with many items (read: line pixels are hidden behind the musical items).

So, when I ran Audiveris application on your score, I noticed the undetected staff and quickly suspected a lack of line segments to derive the staff lines from them. Advantage of the "Constants", any user can modify them, which I did: I reduced the minimum length from 1.0 down to 0.25 the interline value. And the result was OK on this example, so I posted this as a plain and temporary workaround for the case at hand.

Later, I officially committed (0eb1894972a693797deff7513d939e19a14ea1a1) this new value. But, FYI, this introduced a problem with some symbol extraction, that needed to be fixed (see commit d666582361a4541177db091e39286ec2e6a235d9).

These constants are not meant for the casual end user, this must be clear. It's only a low-level mechanism, and most high-level user actions usually end up playing with these hidden low-level constants. We have more than 800 such constants...

Now, how could Audiveris "survive" any score and "recognize only what is sufficiently clear"? In the case at hand, a staff was not detected. Fine. What can Audiveris do with this? It does not even know that it has missed a staff. And what is the concrete meaning of "sufficiently clear", from a software point of view?

Transcribing score images is an endless fight between a (slowly improving) software and a wide population of (sometimes very poor and crowded) images. We have decided to keep the end-user in the driver's seat, and offer visual feedback as well as convenient tools to check, orient and correct the transcribing software. This combination of an OMR engine and an OMR UI has proven to be the most efficient approach, globally.

hmmueller commented 2 years ago

Thanks, and agreement, with all you say (if I may say so - I'm only a small trial user, learning myself how to integrate OMR into my score writing processes).

Re "survive" and "recognize only what is sufficiently clear": These are just my expectations, and, as always with users, also I have only words, but not really clear expectations. Still, to try to explain what I meant:

Harald M.

hbitteur commented 2 years ago

OK, I better understand your needs.

An important point for you is that the OMR engine, when processing a whole book, be able to process the following sheets even if some severe exception is raised in the current sheet. The following sheets may be impacted of course, but rather slightly, most often. All depends on the content of the failing sheet, for example the OMR engine may miss a movement break, which is perhaps the worst case. Other things, like a change in time signature, can be manually fixed rather easily.

I will double-check this "keep going" strategy in OMR engine code. Meanwhile, you can already define sheet selections within a book to circumvent a failing sheet. Better than nothing...

hbitteur commented 1 year ago

No more activity on this issue. Should we close it?