#include #include "OTSMorphology.h" // use verticl line of 3 pixel to erode a image void BErodeVertical3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y, wcounts; if (rows <= 2 || columns <= 2)return; // top line for (x = 0; x < columns; x++) { *(target + x) = 0; } // bottom line for (x = 0; x < columns; x++) { *(target + (DWORD)(rows - 1) * columns + x) = 0; } for (y = 1; y < rows - 1; y++) { for (x = 0; x < columns; x++) { if (*(source + (DWORD)y * columns + x) == 0) { *(target + (DWORD)y * columns + x) = 0; continue; } wcounts = 0; if (*(source + (DWORD)(y - 1) * columns + x) == 255) { wcounts++; } if (*(source + (DWORD)(y + 1) * columns + x) == 255) { wcounts++; } if (wcounts == 2) *(target + (DWORD)y * columns + x) = 255; else *(target + (DWORD)y * columns + x) = 0; } } } // use left 45 degree line of 3 pixel to erode a image void BErodeLeft45Degree3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y, wcounts; if (rows <= 2 || columns <= 2)return; // top line for (x = 0; x < columns; x++) { *(target + x) = 0; } // bottom line for (x = 0; x < columns; x++) { *(target + (DWORD)(rows - 1) * columns + x) = 0; } // left line for (y = 0; y < rows; y++) { *(target + (DWORD)y * columns) = 0; } // right line for (y = 0; y < rows; y++) { *(target + (DWORD)y * columns + columns - 1) = 0; } for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) == 0) { *(target + (DWORD)y * columns + x) = 0; continue; } wcounts = 0; if (*(source + (DWORD)(y - 1) * columns + x - 1) == 255) { wcounts++; } if (*(source + (DWORD)(y + 1) * columns + x + 1) == 255) { wcounts++; } if (wcounts == 2) *(target + (DWORD)y * columns + x) = 255; else *(target + (DWORD)y * columns + x) = 0; } } } // use horizoontal line of 3 pixel to erode a image void BErodeHorizontal3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y, wcounts; if (rows <= 2 || columns <= 2)return; // left line for (y = 0; y < rows; y++) { *(target + (DWORD)y * columns) = 0; } // right line for (y = 0; y < rows; y++) { *(target + (DWORD)y * columns + columns - 1) = 0; } for (y = 0; y < rows; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) == 0) { *(target + (DWORD)y * columns + x) = 0; continue; } wcounts = 0; if (*(source + (DWORD)y * columns + x - 1) == 255) { wcounts++; } if (*(source + (DWORD)y * columns + x + 1) == 255) { wcounts++; } if (wcounts == 2) *(target + (DWORD)y * columns + x) = 255; else *(target + (DWORD)y * columns + x) = 0; } } } // use right 45 degree line of 3 pixel to erode a image void BErodeRight45Degree3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y, wcounts; if (rows <= 2 || columns <= 2)return; // top line for (x = 0; x < columns; x++) { *(target + x) = 0; } // bottom line for (x = 0; x < columns; x++) { *(target + (DWORD)(rows - 1) * columns + x) = 0; } // left line for (y = 0; y < rows; y++) { *(target + (DWORD)y * columns) = 0; } // right line for (y = 0; y < rows; y++) { *(target + (DWORD)y * columns + columns - 1) = 0; } for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) == 0) { *(target + (DWORD)y * columns + x) = 0; continue; } wcounts = 0; if (*(source + (DWORD)(y - 1) * columns + x + 1) == 255) { wcounts++; } if (*(source + (DWORD)(y + 1) * columns + x - 1) == 255) { wcounts++; } if (wcounts == 2) *(target + (DWORD)y * columns + x) = 255; else *(target + (DWORD)y * columns + x) = 0; } } } void BDilateVertical3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y; if (rows <= 2 || columns <= 2)return; // top line for (x = 0; x < columns; x++) { if (*(source + x) != 0) { *(target + x) = 0xff; } } // bottom line for (x = 0; x < columns; x++) { if (*(source + (DWORD)(rows - 1) * columns + x) != 0) { *(target + (DWORD)(rows - 1) * columns + x) = 0xff; } } for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) != 0) { *(target + (DWORD)y * columns + x) = 0xff; *(target + (DWORD)(y - 1) * columns + x) = 255; *(target + (DWORD)(y + 1) * columns + x) = 255; } else *(target + (DWORD)y * columns + x) = 0; } } } void BDilateLeft45Degree3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y; if (rows <= 2 || columns <= 2)return; // top line for (x = 0; x < columns; x++) { if (*(source + x) != 0) { *(target + x) = 0xff; } } // bottom line for (x = 0; x < columns; x++) { if (*(source + (DWORD)(rows - 1) * columns + x) != 0) { *(target + (DWORD)(rows - 1) * columns + x) = 0xff; } } // left line for (y = 0; y < rows; y++) { if (*(source + (DWORD)y * columns) != 0) { *(target + (DWORD)y * columns) = 0xff; } } // right line for (y = 0; y < rows; y++) { if (*(source + (DWORD)y * columns + columns - 1) != 0) { *(target + (DWORD)y * columns + columns - 1) = 0xff; } } for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) != 0) { *(target + (DWORD)y * columns + x) = 0xff; *(target + (DWORD)(y - 1) * columns + x - 1) = 255; *(target + (DWORD)(y + 1) * columns + x + 1) = 255; } else *(target + (DWORD)y * columns + x) = 0; } } } void BDilateHorizontal3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y; if (rows <= 2 || columns <= 2)return; // left line for (y = 0; y < rows; y++) { if (*(source + (DWORD)y * columns) != 0) { *(target + (DWORD)y * columns) = 0xff; } } // right line for (y = 0; y < rows; y++) { if (*(source + (DWORD)y * columns + columns - 1) != 0) { *(target + (DWORD)y * columns + columns - 1) = 0xff; } } for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) != 0) { *(target + (DWORD)y * columns + x) = 0xff; *(target + (DWORD)y * columns + x - 1) = 255; *(target + (DWORD)y * columns + x + 1) = 255; } else *(target + (DWORD)y * columns + x) = 0; } } } void BDilateRight45Degree3(LPBYTE source, LPBYTE target, WORD rows, WORD columns) { WORD x, y; if (rows <= 2 || columns <= 2)return; // top line for (x = 0; x < columns; x++) { if (*(source + x) != 0) { *(target + x) = 0xff; } } // bottom line for (x = 0; x < columns; x++) { if (*(source + (DWORD)(rows - 1) * columns + x) != 0) { *(target + (DWORD)(rows - 1) * columns + x) = 0xff; } } // left line for (y = 0; y < rows; y++) { if (*(source + (DWORD)y * columns) != 0) { *(target + (DWORD)y * columns) = 0xff; } } // right line for (y = 0; y < rows; y++) { if (*(source + (DWORD)y * columns + columns - 1) != 0) { *(target + (DWORD)y * columns + columns - 1) = 0xff; } } for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) != 0) { *(target + (DWORD)y * columns + x) = 0xff; *(target + (DWORD)(y - 1) * columns + x + 1) = 255; *(target + (DWORD)(y + 1) * columns + x - 1) = 255; } else *(target + (DWORD)y * columns + x) = 0; } } } void BErode3(LPBYTE source, LPBYTE target, WORD wDegree, WORD rows, WORD columns) { WORD x, y, i, j, wcounts; if (rows == 1 || columns == 1)return; for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) == 0) { *(target + (DWORD)y * columns + x) = 0; continue; } wcounts = 0; for (i = (WORD)(y - 1); i <= (WORD)(y + 1); i++) { for (j = (WORD)(x - 1); j <= (WORD)(x + 1); j++) { if (*(source + (DWORD)i * columns + j) == 0) { wcounts++; } } } if (wcounts >= wDegree) *(target + (DWORD)y * columns + x) = 0; else *(target + (DWORD)y * columns + x) = 0xff; } } // top line for (x = 1; x < columns - (WORD)1; x++) { if (*(source + x) == 0) { *(target + x) = 0; continue; } wcounts = 0; for (i = 0; i <= 1; i++) { for (j = (WORD)(x - 1); j <= (WORD)(x + 1); j++) { if (*(source + (DWORD)i * columns + j) == 0) wcounts++; } } if (wcounts >= wDegree * 5 / 8) *(target + x) = 0; else *(target + x) = 0xff; } // bottom line for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)(rows - 1) * columns + x) == 0) { *(target + (DWORD)(rows - 1) * columns + x) = 0; continue; } wcounts = 0; for (i = (WORD)(rows - 2); i <= (WORD)(rows - 1); i++) { for (j = (WORD)(x - 1); j <= (WORD)(x + 1); j++) { if (*(source + (DWORD)i * columns + j) == 0) wcounts++; } } if (wcounts >= wDegree * 5 / 8) *(target + (DWORD)(rows - 1) * columns + x) = 0; else *(target + (DWORD)(rows - 1) * columns + x) = 0xff; } // left line for (y = 1; y < rows - 1; y++) { if (*(source + (DWORD)y * columns) == 0) { *(target + (DWORD)y * columns) = 0; continue; } wcounts = 0; for (i = (WORD)(y - 1); i <= (WORD)(y + 1); i++) { for (j = 0; j <= 1; j++) { if (*(source + (DWORD)i * columns + j) == 0) wcounts++; } } if (wcounts >= wDegree * 5 / 8) *(target + (DWORD)y * columns) = 0; else *(target + (DWORD)y * columns) = 0xff; } // right line for (y = 1; y < rows - 1; y++) { if (*(source + (DWORD)y * columns + columns - 1) == 0) { *(target + (DWORD)y * columns + columns - 1) = 0; continue; } wcounts = 0; for (i = (WORD)(y - 1); i <= (WORD)(y + 1); i++) { for (j = (WORD)(columns - 2); j <= (WORD)(columns - 1); j++) { if (*(source + (DWORD)i * columns + j) == 0) wcounts++; } } if (wcounts >= wDegree * 5 / 8) *(target + (DWORD)y * columns + columns - 1) = 0; else *(target + (DWORD)y * columns + columns - 1) = 0xff; } return; } void BDilate3(LPBYTE source, LPBYTE target, WORD wDegree, WORD rows, WORD columns) { WORD x, y, i, j, wcounts; for (y = 1; y < rows - 1; y++) { for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)y * columns + x) != 0) { *(target + (DWORD)y * columns + x) = 0xff; continue; } wcounts = 0; for (i = (WORD)(y - 1); i <= (WORD)(y + 1); i++) { for (j = (WORD)(x - 1); j <= (WORD)(x + 1); j++) { if (*(source + (DWORD)i * columns + j) != 0) wcounts++; } } if (wcounts >= wDegree) *(target + (DWORD)y * columns + x) = 0xff; else *(target + (DWORD)y * columns + x) = 0; } } // top line for (x = 1; x < columns - 1; x++) { if (*(source + x) != 0) { *(target + x) = 0xff; continue; } wcounts = 0; for (i = 0; i <= 1; i++) { for (j = (WORD)(x - 1); j <= (WORD)(x + 1); j++) { if (*(source + (DWORD)i * columns + j) != 0) wcounts++; } } if (wcounts >= wDegree * 5 / 8) // but does not mater, as we have border of 2 now { *(target + x) = 0xff; } else { *(target + x) = 0; } } // bottom line for (x = 1; x < columns - 1; x++) { if (*(source + (DWORD)(rows - 1) * columns + x) != 0) { *(target + (DWORD)(rows - 1) * columns + x) = 0xff; continue; } wcounts = 0; for (i = (WORD)(rows - 2); i <= (WORD)(rows - 1); i++) { for (j = (WORD)(x - 1); j <= (WORD)(x + 1); j++) { if (*(source + (DWORD)i * columns + j) != 0) wcounts++; } } if (wcounts > wDegree * 5 / 8) { *(target + (DWORD)(rows - 1) * columns + x) = 0xff; } else { *(target + (DWORD)(rows - 1) * columns + x) = 0; } } // left line for (y = 1; y < rows - 1; y++) { if (*(source + (DWORD)y * columns) != 0) { *(target + (DWORD)y * columns) = 0xff; continue; } wcounts = 0; for (i = (WORD)(y - 1); i <= (WORD)(y + 1); i++) { for (j = 0; j <= (WORD)1; j++) { if (*(source + (DWORD)i * columns + j) != 0) wcounts++; } } if (wcounts >= wDegree * 5 / 8) { *(target + (DWORD)y * columns) = 0xff; } else { *(target + (DWORD)y * columns) = 0; } } // right line for (y = 1; y < rows - 1; y++) { if (*(source + (DWORD)y * columns + columns - 1) != 0) { *(target + (DWORD)y * columns + columns - 1) = 0xff; continue; } wcounts = 0; for (i = (WORD)(y - 1); i <= (WORD)(y + 1); i++) { for (j = (WORD)(columns - 2); j <= (WORD)(columns - 1); j++) { if (*(source + (DWORD)i * columns + j) != 0) wcounts++; } } if (wcounts >= wDegree * 5 / 8) { *(target + (DWORD)y * columns + columns - 1) = 0xff; } else { *(target + (DWORD)y * columns + columns - 1) = 0; } } // four cornor points treated separately here // top-left if (*(source) != 0) { *target = 0xff; } else { wcounts = 0; if (*(source + 1) != 0) wcounts++; if (*(source + columns) != 0) wcounts++; if (*(source + columns + 1) != 0) wcounts++; // if (wcounts >= wDegree*3/8) // this is a bug here - interger division if (wcounts * 8 >= wDegree * 3) { *target = 0xff; } else { *target = 0; } } //top-right if (*(source + columns - 1) != 0) { *(target + columns - 1) = 0xff; } else { wcounts = 0; if (*(source + columns - 2) != 0) wcounts++; if (*(source + columns * 2 - 1) != 0) wcounts++; if (*(source + columns * 2 - 2) != 0) wcounts++; // if (wcounts >= wDegree*3/8) // this is a bug here - interger division if (wcounts * 8 >= wDegree * 3) { *(target + columns - 1) = 0xff; } else { *(target + columns - 1) = 0; } } //bottom-left if (*(source + (DWORD)columns * (rows - 1)) != 0) { *(target + (DWORD)columns * (rows - 1)) = 0xff; } else { wcounts = 0; if (*(source + (DWORD)columns * (rows - 1) + 1) != 0) wcounts++; if (*(source + (DWORD)columns * (rows - 2)) != 0) wcounts++; if (*(source + (DWORD)columns * (rows - 2) + 1) != 0) wcounts++; // if (wcounts >= wDegree*3/8) // this is a bug here - interger division if (wcounts * 8 >= wDegree * 3) { *(target + (DWORD)columns * (rows - 1)) = 0xff; } else { *(target + (DWORD)columns * (rows - 1)) = 0; } } //bottom-right if (*(source + (DWORD)columns * rows - 1) != 0) { *(target + (DWORD)columns * rows - 1) = 0xff; } else { wcounts = 0; if (*(source + (DWORD)columns * rows - 2) != 0) wcounts++; if (*(source + (DWORD)columns * (rows - 1) - 2) != 0) wcounts++; if (*(source + (DWORD)columns * (rows - 1) - 1) != 0) wcounts++; // if (wcounts >= wDegree*3/8) // this is a bug here - interger division if (wcounts * 8 >= wDegree * 3) { *(target + (DWORD)columns * rows - 1) = 0xff; } else { *(target + (DWORD)columns * rows - 1) = 0; } } return; }