private void process(Gray8Image in, BilevelImage out) { final int HEIGHT = in.getHeight(); final int WIDTH = in.getWidth(); if (out == null) { out = new MemoryBilevelImage(WIDTH, HEIGHT); } final int NUM_ERROR_PIXELS = errorNum.length; // create buffer int[] buffer = new int[newWidth * numRows]; // System.out.println("buffer length=" + buffer.length); // fill buffer with numRows (or HEIGHT, whatever is smaller) rows of data int n = Math.min(numRows, HEIGHT); int offset = leftColumns; int bufferYIndex = 0; while (n-- > 0) { fillBuffer(0, bufferYIndex++, buffer, offset); offset += newWidth; } int bufferLastRowOffset = offset - newWidth; // set complete output image to black out.clear(BilevelImage.BLACK); for (int y = 0; y < HEIGHT; y++) { int bufferIndex = leftColumns; for (int x = 0; x < WIDTH; x++) { int value = buffer[bufferIndex]; if (value < 0) { value = 0; } else if (value > 255) { value = 255; } int error; if ((value & 0x80) == 0) { // black pixel need not be written to output image // because all of its pixels have initially been set // to that color error = value; } else { // white out.putWhite(x, y); error = value - 255; } for (int i = 0; i < NUM_ERROR_PIXELS; i++) { int errorPart = error * errorNum[i] / errorDen[i]; buffer[bufferIndex + indexLut[i]] += errorPart; } bufferIndex++; } for (int i = 0, j = newWidth; j < buffer.length; i++, j++) { buffer[i] = buffer[j]; } if (bufferYIndex < HEIGHT) { fillBuffer(0, bufferYIndex++, buffer, bufferLastRowOffset); } setProgress(y, HEIGHT); } setOutputImage(out); }
private void process(Gray8Image in, Gray8Image out) { final int HEIGHT = in.getHeight(); final int WIDTH = in.getWidth(); final int RIGHT_SHIFT = 8 - grayBits; final int[] GRAY_LUT = new int[1 << grayBits]; for (int i = 0; i < GRAY_LUT.length; i++) { GRAY_LUT[i] = i * 255 / (GRAY_LUT.length - 1); } if (out == null) { out = new MemoryGray8Image(WIDTH, HEIGHT); } final int NUM_ERROR_PIXELS = errorNum.length; // create buffer int[] buffer = new int[newWidth * numRows]; // fill buffer with numRows (or HEIGHT, whatever is smaller) rows of data int n = Math.min(numRows, HEIGHT); int offset = leftColumns; int bufferYIndex = 0; while (n-- > 0) { fillBuffer(0, bufferYIndex++, buffer, offset); offset += newWidth; } int bufferLastRowOffset = offset - newWidth; for (int y = 0; y < HEIGHT; y++) { int bufferIndex = leftColumns; for (int x = 0; x < WIDTH; x++) { int value = buffer[bufferIndex]; if (value < 0) { value = 0; } else if (value > 255) { value = 255; } int quantized = GRAY_LUT[value >> RIGHT_SHIFT]; out.putSample(0, x, y, quantized); int error = value - quantized; for (int i = 0; i < NUM_ERROR_PIXELS; i++) { int errorPart = error * errorNum[i] / errorDen[i]; buffer[bufferIndex + indexLut[i]] += errorPart; } bufferIndex++; } for (int i = 0, j = newWidth; j < buffer.length; i++, j++) { buffer[i] = buffer[j]; } if (bufferYIndex < HEIGHT) { fillBuffer(0, bufferYIndex++, buffer, bufferLastRowOffset); } setProgress(y, HEIGHT); } setOutputImage(out); }
private void fitTemplate() { int startX = 0, startY = 0; int endX = img.getWidth() - bestfit.getTemplate().getWidth(); int endY = img.getHeight() - bestfit.getTemplate().getHeight(); centerTemplate(startX, startY, endX, endY, 3); templateXOR(img, bestfit.getX(), bestfit.getY(), bestfit.getTemplate(), true); sizeTemplate(); aspectTemplate(); shiftTemplate(); sizeTemplate(); aspectTemplate(); shiftTemplate(); templateXOR(img, bestfit.getX(), bestfit.getY(), bestfit.getTemplate(), true); }
private void centerTemplate(int startX, int startY, int endX, int endY, int granularity) { int stepX = bestfit.getTemplate().getWidth() / granularity; int stepY = bestfit.getTemplate().getHeight() / granularity; // System.out.println("stepX = " + stepX + ": stepY = " + stepY); double maxsim = -1; int simi = -1, simj = -1; for (int iCount = startX; iCount <= endX; iCount += stepX) { for (int jCount = startY; jCount <= endY; jCount += stepY) { double currsim = 1.0 - templateXOR(img, iCount, jCount, bestfit.getTemplate(), false); // System.out.println(i + ":" + j + ":" + currsim); if (maxsim == -1 || maxsim < currsim) { maxsim = currsim; simi = iCount; simj = jCount; } } } // System.out.println("--- maxsim = " + maxsim + ":" // + simi + ":" + simj); if (maxsim > 0.5) { if (stepX >= 4) { // up to an accuracy of 2 pixels centerTemplate( Math.max(simi - stepX / 2, 0), Math.max(simj - stepY / 2, 0), Math.min(simi + stepX / 2, img.getWidth()), Math.min(simj + stepY / 2, img.getHeight()), granularity * 2); } else { bestfit.setX(simi); bestfit.setY(simj); bestfit.setSim(maxsim); } } }
/** * Returns the number of black and white differences between the template and exam file. * * @param img Image of exams * @param x x start coordinate of the file * @param y y start coordinate of the file * @param template Template of exams * @param dump Dump to screen * @return The difference */ public static double templateXOR( Gray8Image img, int x, int y, Gray8Image template, boolean dump) { int diff = 0, total = 0; for (int j = y; j < y + template.getHeight() && j < img.getHeight(); j++) { for (int i = x; i < x + template.getWidth() && i < img.getWidth(); i++) { // XXX boolean isblack = (img.getSample(i, j) < 200 ? true : false); // if(dump) { System.out.print((isblack // & template.isWhite(i - x, j - y) ? "1" : ((!isblack) // & template.isBlack(i - x, j - y)) ? "-" : "0")); } if ((isblack & template.isWhite(i - x, j - y) | (!isblack) & template.isBlack(i - x, j - y))) { diff++; } total++; } // if(dump) { System.out.println(); } } return ((double) diff) / total; }
private void fillTemplate( Gray8Image templateimg, double outerdiamX, double innerdiamX, double aspect) { double centerX = templateimg.getWidth() / 2; double centerY = templateimg.getHeight() / 2; double outerrad = outerdiamX / 2; double innerrad = innerdiamX / 2; for (int wCount = 0; wCount < templateimg.getWidth(); wCount++) { for (int hCount = 0; hCount < templateimg.getHeight(); hCount++) { double dist = Math.sqrt( (wCount - centerX) * (wCount - centerX) + (hCount - centerY) / aspect * (hCount - centerY) / aspect); if (dist <= outerrad && dist > innerrad) { templateimg.putBlack(wCount, hCount); } else { templateimg.putWhite(wCount, hCount); } } } }