c++ - Sobel Edge Detection without a buffer -
for embedded design attempting implement sobel's edge detection on board without use of buffer. i.e. reading , writing directly screen. can however, store 1 or 2 imge width full of data referenced later. due limitations set forth board. have fallen issue. recieve noise regardless if attempt sobel or edge detection algorithm. code below, have suggestions
version 1
void sobeledgedetection2() { int gx[3][3]; int gy[3][3]; int sumx[3]; int sumy[3]; int sum[3]; int pix = 0; int piy = 0; //uint8_t r, g, b = 0; int i, j = 0; //unpackedcolour pixval; uint16_t *buffer; // allocate space scan lines , odd scan lines buffer = new uint16_t[_gl->getwidth()]; //buffer previous line uint16_t *buft; // allocate space scan lines , odd scan lines buft = new uint16_t[_gl->getwidth()]; // masks ////////////////////////////////////// //x// gx[0][0] = -1; gx[0][1] = 0; gx[0][2] = 1; gx[1][0] = -2; gx[1][1] = 0; gx[1][2] = 2; gx[2][0] = -1; gx[2][1] = 0; gx[2][2] = 1; //y// gy[0][0] = 1; gy[0][1] = 2; gy[0][2] = 1; gy[1][0] = 0; gy[1][1] = 0; gy[1][2] = 0; gy[2][0] = -1; gy[2][1] = -2; gy[2][2] = -1; (int y = 0; y < _gl->getheight(); y++) { (int x = 0; x < _gl->getwidth(); x++) { sumx[0] = sumx[1] = sumx[2] = 0; sumy[0] = sumy[1] = sumy[2] = 0; if (y == 0 || y == _gl->getheight() - 1) { sum[0] = sum[1] = sum[2] = 0; } else if (x == 0 || x == _gl->getwidth() - 1) { sum[0] = sum[1] = sum[2] = 0; } else { (i = -1; <= 1; i++) { (j = -1; j <= 1; j++) { pix = j + x; piy = + y; pixel16 pix = getpixel(pix, piy); uint8_t red = pix.red; uint8_t green = pix.green; uint8_t blue = pix.blue; sumx[0] += (red) * gx[j + 1][i + 1]; sumx[1] += (green) * gx[j + 1][i + 1]; sumx[2] += (blue) * gx[j + 1][i + 1]; sumy[0] += (red) * gy[j + 1][i + 1]; sumy[1] += (green) * gy[j + 1][i + 1]; sumy[2] += (blue) * gy[j + 1][i + 1]; } } sum[0] = abs(sumx[0]) + abs(sumy[0]); sum[1] = abs(sumx[1]) + abs(sumy[1]); sum[2] = abs(sumx[2]) + abs(sumy[2]); } if (sum[0] > 255) sum[0] = 255; if (sum[0] < 0) sum[0] = 0; if (sum[1] > 255) sum[1] = 255; if (sum[1] < 0) sum[1] = 0; if (sum[2] > 255) sum[2] = 255; if (sum[2] < 0) sum[2] = 0; int newpixel[3]; newpixel[0] = (255 - ((unsigned char) (sum[0]))); newpixel[1] = (255 - ((unsigned char) (sum[1]))); newpixel[2] = (255 - ((unsigned char) (sum[2]))); pixel16 pix(newpixel[0], newpixel[1], newpixel[2]); buffer[x] = packcolour(pix).packed565; } //need move cursor // draw this->paintrow(point(0, y), buffer, _gl->getwidth()); } delete[] buffer; } version2
/** * https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/image-processing/edge_detection.html * 1 iterate on every pixel in image * 2 apply x gradient kernel * 3 apply y gradient kernel * 4 find length of gradient using pythagoras' theorem * 5 normalise gradient length range 0-255 * 6 set pixels new values */ void sobeledgedetection4() { unpackedcolour colour; (int x = 1; x < _gl->getwidth() - 1; x++) { (int y = 1; y < _gl->getheight() - 1; y++) { // initialise gx , gy 0 int gx = 0; int gy = 0; unsigned int intensity = 0; // left column pixel16 pixel = this->getpixel(x - 1, y - 1); intensity = pixel.red + pixel.green + pixel.blue; gx += -intensity; gy += -intensity; pixel = this->getpixel(x - 1, y); intensity = pixel.red + pixel.green + pixel.blue; gx += -2 * intensity; pixel = this->getpixel(x - 1, y + 1); intensity = pixel.red + pixel.green + pixel.blue; gx += -intensity; gy += +intensity; // middle column pixel = this->getpixel(x, y - 1); intensity = pixel.red + pixel.green + pixel.blue; gy += -2 * intensity; pixel = this->getpixel(x, y + 1); intensity = pixel.red + pixel.green + pixel.blue; gy += +2 * intensity; // right column pixel = this->getpixel(x + 1, y - 1); intensity = pixel.red + pixel.green + pixel.blue; gx += +intensity; gy += -intensity; pixel = this->getpixel(x + 1, y); intensity = pixel.red + pixel.green + pixel.blue; gx += +2 * intensity; pixel = this->getpixel(x + 1, y + 1); intensity = pixel.red + pixel.green + pixel.blue; gx += +intensity; gy += +intensity; // calculate gradient length unsigned int length = (unsigned int) sqrt( (float) (gx * gx) + (float) (gy * gy)); // normalise length 0 255 length = length / 17; // draw pixel on edge image pixel16 pixel2(length,length,length); this->setpixel(x, y, pixel2); } } } version 3
// sobel map x axis const double _sobel_gx[3][3] = { { -1.0, +0.0, +1.0 }, { -2.0, +0.0, +2.0 }, { -1.0, +0.0, +1.0 } }; // sobel map y axis const double _sobel_gy[3][3] = { { +1.0, +2.0, +1.0 }, { +0.0, +0.0, +0.0 }, { -1.0, -2.0, -1.0 } }; double get_sobel_gradient(int width, int height, int x, int y) { double sobel_gradient_x = 0, sobel_gradient_y = 0; int mx = 0, = 0, sx = 0, sy = 0; (mx = x; mx < x + 3; mx++) { sy = 0; (my = y; < y + 3; my++) { if (mx < width && < height) { //int r, g, b, idx; int idx = (mx + width * my) * 3; pixel16 pixval = this->getpixel(idx); //r = pixval.red; //g = pixval.green; //b = pixval.blue; unpackedcolour col = this->packcolour(pixval); sobel_gradient_x += col.packed565 * _sobel_gx[sx][sy]; sobel_gradient_y += col.packed565 * _sobel_gy[sx][sy]; } sy++; } sx++; } return abs(sobel_gradient_x) + abs(sobel_gradient_y); } void sobeledgedetection3() { double threshold = 50000.0; unpackedcolour colour; (int y = 0; y < _gl->getheight(); y++) { (int x = 0; x < _gl->getwidth(); x++) { if (get_sobel_gradient(_gl->getwidth(), _gl->getheight(), x, y) >= threshold) { colour.packed565 = 0x0000; //set white } else { colour.packed565 = 0xffff; //set black } this->setpixel(x, y, colour); } } }
for version 1, after allocate 2 buffers (just use buffer , buft), create 2 pointers point current , previous rows, this:
uint16_t *currentrow = buffer; uint16_t *prevrow = buft; inside row loop, write currentrow instead of buffer:
pixel16 pix(newpixel[0], newpixel[1], newpixel[2]); currentrow[x] = packcolour(pix).packed565; because sobel filter reads previous row, can't overwrite row until after have finished calculating filtered values row after it. @ end of loop, calling paintrow(), draw previous row (if 1 exists), , swap buffers current becomes previous, , previous becomes new current row (to overwritten on next pass through loop). on last row current row drawn, because otherwise won't since outer loop terminate.
if(y > 0) // draw previous row if not first row: this->paintrow(point(0, y-1), prevrow, _gl->getwidth()); if(y == _gl->getheight()-1) // draw current row if last: this->paintrow(point(0, y), currentrow, _gl->getwidth()); // swap row pointers: uint16_t *temp = prevrow; prevrow = currentrow; currentrow = temp; the same strategy should work other versions.
Comments
Post a Comment