Simple Black And White Drawing
I am trying to detect lines, circles and arcs in a simple black and white drawing image file (jpg or bmp format)
I posted a similar question before, in which OpenCV library was suggested. It is a good library, however, it is not accurate enough for my purpose. More specifically, the Canny detection algorithm somehow does not work perfectly for my images.
Hence I am trying to implement the algorithm myself using QImage. I have managed to successfully implement it for straight lines. The code in Qt C++ is as follows. It is a very cluttered code, but I am just giving it for reference.
The algorithm is very simple:
1. I scan the image from top left, row-wise.
2. Whenever I encounter a black pixel, I scan towards its right, left bottom to check whether it is a corner of a line segment.
for ( int i = 0; i < myImage.height(); i++ ) { for ( int j = 0; j < myImage.width(); j++ ) { if ( qGray( myImage.pixel( j, i ) ) == 0 ) { myImage.setPixel( j, i, value ); bool horiLineDrawn = false; int xRight = j+1, xLeft = j-1; int y = i+1; while ( xRight < myImage.width() && qGray( myImage.pixel( xRight, i ) ) == 0 ) { myImage.setPixel( xRight, i, value ); xRight++; } while ( y < myImage.height() && xLeft >= 0 && qGray( myImage.pixel( xLeft, y ) ) == 0 ) { if ( xLeft - 1 >= 0 && qGray( myImage.pixel( xLeft - 1, y ) ) == 0 ) { while ( xLeft >= 0 && qGray( myImage.pixel( xLeft, y ) ) == 0 ) { myImage.setPixel( xLeft, y, value ); xLeft--; } y++; } else if ( y+1 < myImage.height() && qGray( myImage.pixel( xLeft, y + 1 ) ) == 0 ) { while ( y < myImage.height() && qGray( myImage.pixel( xLeft, y ) ) == 0 ) { myImage.setPixel( xLeft, y, value ); y++; } xLeft--; } else { xLeft--; y++; } } y--; xLeft++; if ( y > i && ( y - i > MIN_PIXELS_LINE || xRight-1 - xLeft > MIN_PIXELS_LINE ) ) { drawFile.Line( fileName2, xRight-1, myImage.height() - i, xLeft, myImage.height() - y, 0 ); horiLineDrawn = true; } y = i + 1; while ( y < myImage.height() && xRight < myImage.width() && qGray( myImage.pixel( xRight, y ) ) == 0 ) { if ( xRight + 1 < myImage.width() && qGray( myImage.pixel( xRight + 1, y ) ) == 0 ) { while ( xRight < myImage.width() && qGray( myImage.pixel( xRight, y ) ) == 0 ) { myImage.setPixel( xRight, y, value ); xRight++; } y++; } else if ( y+1 < myImage.height() && qGray( myImage.pixel( xRight, y + 1 ) ) == 0 ) { while ( y < myImage.height() && qGray( myImage.pixel( xRight, y ) ) == 0 ) { myImage.setPixel( xRight, y, value ); y++; } xRight++; } else { xRight++; y++; } } y--; xRight--; if ( y - i > MIN_PIXELS_LINE || xRight - j > MIN_PIXELS_LINE && !horiLineDrawn) { drawFile.Line( fileName2, j, myImage.height() - i, xRight, myImage.height() - y, 0 ); horiLineDrawn = true; } y = i + 1; while ( y < myImage.height() && qGray( myImage.pixel( j, y ) ) == 0 ) { myImage.setPixel( j, y, value ); y++; } xLeft = j - 1; xRight = j + 1; if ( xLeft >= 0 && y < myImage.height() && qGray( myImage.pixel( xLeft, y ) ) == 0 ) { while ( xLeft >= 0 && y < myImage.height() && qGray( myImage.pixel( xLeft, y ) ) == 0 ) { while ( y < myImage.height() && qGray( myImage.pixel( xLeft, y ) ) == 0 ) { myImage.setPixel( xLeft, y, value ); y++; } xLeft--; } xLeft++; y--; if ( y - i > MIN_PIXELS_LINE || j - xLeft > MIN_PIXELS_LINE ) drawFile.Line( fileName2, j, myImage.height() - i, xLeft, myImage.height() - y, 0 ); } else if ( xRight < myImage.width() && y < myImage.height() && qGray( myImage.pixel( xRight, y ) ) == 0 ) { while ( xRight < myImage.width() && y < myImage.height() && qGray( myImage.pixel( xRight, y ) ) == 0 ) { while ( y < myImage.height() && qGray( myImage.pixel( xRight, y ) ) == 0 ) { myImage.setPixel( xRight, y, value ); y++; } xRight++; } xRight--; y--; if ( y - i > MIN_PIXELS_LINE || xRight - j > MIN_PIXELS_LINE ) drawFile.Line( fileName2, j, myImage.height() - i, xRight, myImage.height() - y, 0 ); } else { y--; if ( y - i > MIN_PIXELS_LINE ) drawFile.Line( fileName2, j, myImage.height() - i, j, myImage.height() - y, 0 ); } } } }
This works fine. For example:
Input image:
Output image:
Can anyone suggest how I can implement similar or better algorithm for circles and arcs? Efficiency is not a problem since my image size shall be maximum 1000 by 1000 pixels. However, accuracy is critical.
EDIT: There may be a lot of bugs in my present implementation of straight lines, like I haven't tested it for intersecting lines etc. But I think I shall be able to manage those complications.
Simple Black And White Drawing
Source: https://stackoverflow.com/questions/19912454/detect-lines-circles-and-arcs-in-simple-black-and-white-drawing-image
Posted by: walshculdrought78.blogspot.com
0 Response to "Simple Black And White Drawing"
Post a Comment