Reputation: 1524
I'm building a app that uses images from a webservice. Unfortunatly the images are padded with white (when the service resized them, long time ago).
I want to make a class that detects if the image has complete lines, horizontal or vertical, of the same white nuance, and then crop the image. (or remove the white area)
So basically i'm thinking: - Run through the horizontal lines (full width and 1 px height) and check if it has the same white nuance all across.
(To optimize later i could detect the color by detectiong firsk and last pixel and if they matches then check half way etc.) - Not important in first draft.
Regarding the padding, i cant be sure about the size of the padding. The images is in various sizes and proportions and padded to be the same size. So the padded borders changes from image to image.
EDIT: Here is one: http://i.dbastatic.dk/images/3/37//74438337_30052011063215_9539_3.jpg and a vertical one: http://i.dbastatic.dk/images/3/40//74273140_23052011090107_0806_3.jpg and a tricky one: http://i.dbastatic.dk/images/3/61/500396561_27052011171605_5877_3.jpg note that the last has partly white background, why i need to detect if the white-ish pixels goes all across the image width.
Could yo please give me a code example to get started. The hard part, i think, is to run trough the image pixel-wise and detect the color.
Maybe C++ would be much faster to do his?
I'm capable of Both C++ and Objective-C so give me your best shot :-)
Upvotes: 0
Views: 2158
Reputation: 3852
NSImage* yourImage;
NSBitmapImageRep *bitmapRep = [NSBitmapImageRep imageRepWithData:[yourImage TIFFRepresentation]];
unsigned char* pixelData = [bitmapRep bitmapData];
The pixels are probably in RGB format, so from here it should be easy to traverse the image pixel by pixel.
You can check the data format:
int depth = [bitmapRep bitsPerSample];
int channels = [bitmapRep samplesPerPixel];
int height = [bitmapRep size].height;
int width = [bitmapRep size].width;
EDIT: In order to verify Wajih's claims I wrote a little (quick & dirty) test program, I need some help to determine the border with the Hough transform though:
EDIT2: I realized that Wajih was referring to a special Hough transform (kht) implementation (not the OpenCV version), I have no time measurement for the kht. I updated the source code to handle jpg compression artefacts.
std::string origFileName("../data/500396561_27052011171605_5877_3.jpg");
cv::Mat image = cv::imread(origFileName, 0);
std::cout << __PRETTY_FUNCTION__ << " -- widht, height = " << image.cols << ", " << image.rows << std::endl;
QElapsedTimer naiveTimer;
naiveTimer.start();
unsigned int x1 = 0;
unsigned int y1 = 0;
unsigned int x2 = 0;
unsigned int y2 = 0;
const unsigned int thresholdColor = 15; // how much may the color deviate
const unsigned int thresholdPixel = 5; // how many false detections do you want to tolerate
for (unsigned int ii = 0; ii < 1000; ++ii)
{
x1 = y1 = x2 = y2 = 0;
unsigned char* pixel = image.ptr<unsigned char>(0);
unsigned char border = *pixel;
bool top = true;
// horizontal border lines
for (int yy = 0; yy < image.rows; ++yy)
{
pixel = image.ptr<unsigned char>(yy);
int count = 0;
for (int xx = 0; xx < image.cols; ++xx)
{
if (255 - *pixel < thresholdColor)
++count;
++pixel;
}
if (image.cols - count < thresholdPixel)
{
if (top) ++y1;
else ++y2;
}
else top = false;
}
y2 = image.rows - y2;
// vertical border lines
bool left = true;
pixel = image.ptr<unsigned char>(0);
unsigned int offset = image.ptr<unsigned char>(1) - pixel;
for (int xx = 0; xx < image.cols; ++xx)
{
int count = 0;
unsigned char* colPixel = pixel++;
for (int yy = 0; yy < image.rows; ++yy)
{
if (255 - *colPixel < thresholdColor)
++count;
colPixel += offset;
}
if (image.rows - count < thresholdPixel)
{
if (left) ++x1;
else ++x2;
}
else left = false;
}
x2 = image.cols - x2;
}
std::cout << __PRETTY_FUNCTION__ << " -- Time elapsed: " << naiveTimer.elapsed() << std::endl;
std::cout << __PRETTY_FUNCTION__ << " -- x1 y1 x2 y2: " << x1 << " " << y1 << " " << x2 << " " << y2 << std::endl;
QImage original(origFileName.c_str());
QImage cropped = original.copy(x1, y1, x2 - x1, y2 - y1);
EHVhu.jpg (the image that I used for testing, besides the images provided by esbenr):
Upvotes: 1
Reputation:
What you need to do is to adopt a better and faster algorithm. You can use Hough transform algorithms to detect lines. here you can even set the width and the length of the lines to be detected. This link might be useful Here. If you have any experience of OpenCV, you can use its built in fast methods to do a hough transform line detection. Probably you should check first if it is portable to Cocoa.
Upvotes: 0