#include #include #include #include "BlobBase.h" void pretest(double x) { // printf("fff %f \n", x); } #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) int GetType(int nvalue, int *qx_list) { qx_list[ERR_TYPE_1] = !!(nvalue & Value_ERR_TYPE_1); qx_list[ERR_TYPE_2] = !!(nvalue & Value_ERR_TYPE_2); return qx_list[ERR_TYPE_1] | qx_list[ERR_TYPE_2]; } void AddErrorScan(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int mdx, int *pErrClass) { if (curRow->scanCount < _MAX_ERROR_SCAN_LINE_PER_ROW) { int lastScanLineIndex = curRow->scanCount++; ERROR_DOTS_SCAN_DATA *scan = curRow->errorScanLineTab + lastScanLineIndex; scan->x = x; scan->count = len; int ex = x + len - 1; scan->energy = difSum; scan->area = scan->count; scan->xposSum = (x + (len >> 1)) * len; scan->yposSum = y * len; scan->minx = x; scan->miny = y; scan->maxx = ex; scan->maxy = y; scan->macro = mdx; for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) { scan->ErrClass[ec] = pErrClass[ec]; } curRow->macro[scan->macro] = len; int linkIndexTab[_MAX_ERROR_SCAN_LINE_PER_ROW]; int linkCount = 0; if (prevRow) { for (int t = 0; t < _MAX_MACRO_COUNT; t++) { curRow->macro[t] += prevRow->macro[t]; // prevRow->macro[t]=0; } int prevLastScanLineIndex = prevRow->scanCount - 1; ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) { int psx = pscan->x - 1; int pex = psx + pscan->count - 1 + 1; // sxg modified waitting for valid 9.5 if (x <= pex && ex >= psx) { if (pscan->area > 0) { int area = scan->area + (pscan->area); scan->area = area; if (scan->macro != pscan->macro) { if (scan->macro < pscan->macro) scan->macro = pscan->macro; } scan->energy += pscan->energy; scan->xposSum += pscan->xposSum; scan->yposSum += pscan->yposSum; scan->minx = min(scan->minx, pscan->minx); scan->miny = min(scan->miny, pscan->miny); scan->maxx = max(scan->maxx, pscan->maxx); scan->maxy = max(scan->maxy, pscan->maxy); pscan->area = 0; pscan->energy = lastScanLineIndex; for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) { scan->ErrClass[ec] = pErrClass[ec] + (pscan->ErrClass[ec]); } linkIndexTab[/*0xff & */ (linkCount++)] = prevLastScanLineIndex; } // else //{ // int bindex = 0xff & pscan->energy; // ERROR_DOTS_SCAN_DATA * hscan = curRow->errorScanLineTab + bindex; // hscan->count = ex - hscan->x + 1; // hscan->area += scan->area; // hscan->energy += scan->energy; // hscan->xposSum += scan->xposSum; // hscan->yposSum += scan->yposSum; // hscan->minx = min(scan->minx , hscan->minx); // hscan->miny = min(scan->miny , hscan->miny); // hscan->maxx = max(scan->maxx , hscan->maxx); // hscan->maxy = max(scan->maxy , hscan->maxy); // scan->area = 0; // for(;linkCount > 0 ; --linkCount) // { // ERROR_DOTS_SCAN_DATA * p = prevRow->errorScanLineTab + linkIndexTab[0xff & (linkCount - 1)]; // p->energy = bindex; // } // curRow->scanCount--; // break; // } } } } } } void LinkScanLineToBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width) { if (prevRow) { int prevLastScanLineIndex = prevRow->scanCount - 1; ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; // int minArea = param->minArea; // int minEnergy = param->minEnergy; for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) { if (pscan->area > 0) { int x = pscan->xposSum / pscan->area + sx; int y = pscan->yposSum / pscan->area + sy; int minx = pscan->minx + sx; int miny = pscan->miny + sy; int maxx = pscan->maxx + sx; int maxy = pscan->maxy + sy; if (x < width) { int blobIndex = blobs->blobCount; // int mergeDistance = param->mergeDistance; ERROR_DOTS_BLOB_DATA *pblob = blobs->blobTab + blobIndex - 1; int left = minx - mergeDistanceX, right = maxx + mergeDistanceX; int top = miny - mergeDistanceY, bottom = maxy + mergeDistanceY; for (int i = blobIndex - 1; i >= 0; --i, --pblob) { if (1) { if (pblob->maxy > top && pblob->miny < bottom) { if (pblob->maxx > left && pblob->minx < right) { int area = pblob->area + pscan->area; pblob->x = (pblob->x * pblob->area + x * pscan->area) / area; pblob->y = (pblob->y * pblob->area + y * pscan->area) / area; pblob->area = area; for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) { pblob->ErrClass[ec] += pscan->ErrClass[ec]; } pblob->energy += pscan->energy; pblob->minx = min(pblob->minx, minx); pblob->miny = min(pblob->miny, miny); pblob->maxx = max(pblob->maxx, maxx); pblob->maxy = max(pblob->maxy, maxy); pblob->macro[pscan->macro] += prevRow->macro[pscan->macro]; prevRow->macro[pscan->macro] -= pscan->area; blobIndex = _MAX_ERROR_DOT_BLOB; break; } } } } if (pscan->area > minArea /*|| pscan->energy > minEnergy*/) { if (blobIndex < _MAX_ERROR_DOT_BLOB) { pblob = blobs->blobTab + blobIndex; pblob->x = x; pblob->y = y; pblob->area = pscan->area; pblob->energy = pscan->energy; pblob->minx = minx; pblob->miny = miny; pblob->maxx = maxx; pblob->maxy = maxy; blobs->blobCount++; for (int t = 0; t < _MAX_MACRO_COUNT; t++) { pblob->macro[t] = 0; } pblob->macro[pscan->macro] = pscan->area; prevRow->macro[pscan->macro] -= pscan->area; // prevRow->macro[pscan->macro]=0; for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) { pblob->ErrClass[ec] = pscan->ErrClass[ec]; } } } } } pscan->area = 0; for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) { pscan->ErrClass[ec] = 0; } } // for (int t=0;tmacro[t]+=prevRow->macro[t]; // prevRow->macro[t]=0; // } } } void MergeBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOB_PARAM *param) { int count = blobs->blobCount; ERROR_DOTS_BLOB_DATA *blob = blobs->blobTab + count - 1; int pace = param->mergeDistance; for (int i = count - 1; i > 0; --i, --blob) { int minx = blob->minx; int miny = blob->miny; int maxx = blob->maxx; int maxy = blob->maxy; int energy = blob->energy; int left = minx - pace, right = maxx + pace; int top = miny - 1, bottom = maxy + 1; ERROR_DOTS_BLOB_DATA *pblob = blob - 1; for (int j = i - 1; j >= 0; --j, --pblob) { if (pblob->ErrType == blob->ErrType) { if (pblob->maxy > top && pblob->miny < bottom) { if (pblob->maxx > left && pblob->minx < right) { int areaSum = pblob->area + blob->area; int x = blob->x, y = blob->y; pblob->x = (pblob->x * pblob->area + x * blob->area) / areaSum; pblob->y = (pblob->y * pblob->area + y * blob->area) / areaSum; pblob->area = areaSum; for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) { pblob->ErrClass[ec] += blob->ErrClass[ec]; } pblob->energy += energy; pblob->minx = min(pblob->minx, minx); pblob->miny = min(pblob->miny, miny); pblob->maxx = max(pblob->maxx, maxx); pblob->maxy = max(pblob->maxy, maxy); for (int t = 0; t < _MAX_MACRO_COUNT; t++) { pblob->macro[t] += blob->macro[t]; blob->macro[t] = 0; } count--; memmove(blob, blob + 1, (count - i) * sizeof(blob[0])); break; } } } } } blobs->blobCount = count; } // static int __cdecl compareBlob(const void * p1, const void * p2) static int compareBlob(const void *p1, const void *p2) { ERROR_DOTS_BLOB_DATA *b1 = (ERROR_DOTS_BLOB_DATA *)p1; ERROR_DOTS_BLOB_DATA *b2 = (ERROR_DOTS_BLOB_DATA *)p2; return (b2->area) - (b1->area); } void SortBlob(ERROR_DOTS_BLOBS *blobs) { int count = blobs->blobCount; ERROR_DOTS_BLOB_DATA *blob = blobs->blobTab; qsort(blob, count, sizeof(blob[0]), compareBlob); } // 当前行和前面行合并 void AddErrorScan_New(ERROR_DOTS_SCAN_ROW *curRow, ERROR_DOTS_SCAN_ROW *prevRow, int x, int len, int y, int difSum, int minArea, int minEng, int errorType) { if (curRow->scanCount < _MAX_ERROR_SCAN_LINE_PER_ROW) { int lastScanLineIndex = curRow->scanCount++; ERROR_DOTS_SCAN_DATA *scan = curRow->errorScanLineTab + lastScanLineIndex; scan->x = x; scan->count = len; int ex = x + len - 1; scan->energy = difSum; scan->area = scan->count; scan->xposSum = (x + (len >> 1)) * len; scan->yposSum = y * len; scan->minx = x; scan->miny = y; scan->maxx = ex; scan->maxy = y; scan->type = errorType; if (prevRow) { int prevLastScanLineIndex = prevRow->scanCount - 1; ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) { int psx = pscan->x - 1; int pex = psx + pscan->count - 1 + 1; if (x <= pex && ex >= psx && pscan->type == scan->type) { if (pscan->area > 0) { int area = scan->area + (pscan->area); scan->area = area; scan->energy += pscan->energy; scan->xposSum += pscan->xposSum; scan->yposSum += pscan->yposSum; scan->minx = min(scan->minx, pscan->minx); scan->miny = min(scan->miny, pscan->miny); scan->maxx = max(scan->maxx, pscan->maxx); scan->maxy = max(scan->maxy, pscan->maxy); pscan->area = 0; pscan->energy = lastScanLineIndex; } } } } } } void LinkScanLineToBlob_New(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_SCAN_ROW *prevRow, int sx, int sy, int minArea, int minEnergy, int mergeDistanceX, int mergeDistanceY, int width) { if (prevRow) { int prevLastScanLineIndex = prevRow->scanCount - 1; ERROR_DOTS_SCAN_DATA *pscan = prevRow->errorScanLineTab + prevLastScanLineIndex; // int minArea = param->minArea; // int minEnergy = param->minEnergy; for (; prevLastScanLineIndex >= 0; --prevLastScanLineIndex, --pscan) { if (pscan->area > 0) { int x = pscan->xposSum / pscan->area + sx; int y = pscan->yposSum / pscan->area + sy; int minx = pscan->minx + sx; int miny = pscan->miny + sy; int maxx = pscan->maxx + sx; int maxy = pscan->maxy + sy; if (x < width) { int blobIndex = blobs->blobCount; // int mergeDistance = param->mergeDistance; ERROR_DOTS_BLOB_DATA *pblob = blobs->blobTab + blobIndex - 1; int left = minx - mergeDistanceX, right = maxx + mergeDistanceX; int top = miny - mergeDistanceY, bottom = maxy + mergeDistanceY; for (int i = blobIndex - 1; i >= 0; --i, --pblob) { if (pblob->ErrType == pscan->type) { if (pblob->maxy > top && pblob->miny < bottom) { if (pblob->maxx > left && pblob->minx < right) { int area = pblob->area + pscan->area; pblob->x = (pblob->x * pblob->area + x * pscan->area) / area; pblob->y = (pblob->y * pblob->area + y * pscan->area) / area; pblob->area = area; // for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) // { // pblob->ErrClass[ec] += pscan->ErrClass[ec]; // } pblob->energy += pscan->energy; pblob->minx = min(pblob->minx, minx); pblob->miny = min(pblob->miny, miny); pblob->maxx = max(pblob->maxx, maxx); pblob->maxy = max(pblob->maxy, maxy); // pblob->macro[pscan->macro] += prevRow->macro[pscan->macro]; // prevRow->macro[pscan->macro] -= pscan->area; blobIndex = _MAX_ERROR_DOT_BLOB; break; } } } } if (pscan->area > minArea /*|| pscan->energy > minEnergy*/) { if (blobIndex < _MAX_ERROR_DOT_BLOB) { pblob = blobs->blobTab + blobIndex; pblob->x = x; pblob->y = y; pblob->area = pscan->area; pblob->energy = pscan->energy; pblob->ErrType = pscan->type; pblob->minx = minx; pblob->miny = miny; pblob->maxx = maxx; pblob->maxy = maxy; blobs->blobCount++; // for (int t = 0; t < _MAX_MACRO_COUNT; t++) // { // pblob->macro[t] = 0; // } // pblob->macro[pscan->macro] = pscan->area; // prevRow->macro[pscan->macro] -= pscan->area; // prevRow->macro[pscan->macro]=0; // for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) // { // pblob->ErrClass[ec] = pscan->ErrClass[ec]; // } } } } } pscan->area = 0; for (int ec = 0; ec < _MAX_ERR_CLASS; ec++) { pscan->ErrClass[ec] = 0; } } // for (int t=0;tmacro[t]+=prevRow->macro[t]; // prevRow->macro[t]=0; // } } } int GetBlobs_V2(ERROR_DOTS_BLOBS *blobs, unsigned char *pImgdata, unsigned char *pErrordata, int width, int height, int basev, int minArea) { if (blobs == NULL || pErrordata == NULL) { return 1; } int pitch = width; int offset; int point_is_err = 0; int wLineErrsList = 0; int errPos_xList = 0; int difSumList = 0; int point_is_errList = 0; // memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS)); ERROR_DOTS_SCAN_ROW rowDataTab[2]; ERROR_DOTS_SCAN_ROW *curRow = 0; ERROR_DOTS_SCAN_ROW *prevRow = 0; int MIN_AREA = minArea; if (minArea <= 0) { MIN_AREA = 10; } int minEnergy = 2; int mergeDistanceX = 0; int mergeDistanceY = 0; offset = 0; int nErrorType = 0; int lasttype = -1; for (int y = 0; y < height; y++) { wLineErrsList = 0; difSumList = 0; curRow = rowDataTab + (y & 1); curRow->scanCount = 0; offset = y * pitch - 1; nErrorType = -1; lasttype = -1; int kh = 0; for (int x = 0; x < width; x++) { offset++; point_is_err = 0; if (pErrordata[offset] != 0 && pImgdata[offset] > basev) { point_is_err = 1; difSumList += 1; wLineErrsList++; errPos_xList = x; kh = 1; } else // 没有残点 所有缺陷都需要判断是否截止 { // 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点 if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); wLineErrsList = 0; difSumList = 0; } kh = 0; } if (x == width - 1) { if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); } } } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); prevRow = curRow; } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); ERROR_DOTS_BLOB_PARAM blobParam; memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM)); blobParam.mergeDistance = 1; MergeBlob(blobs, &blobParam); SortBlob(blobs); return 0; } int GetBlobs_V3(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, int width, int height, int minArea) { if (blobs == NULL || pErrordata == NULL) { return 1; } int pitch = width; int offset; int point_is_err = 0; int wLineErrsList = 0; int errPos_xList = 0; int difSumList = 0; int point_is_errList = 0; // memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS)); ERROR_DOTS_SCAN_ROW rowDataTab[2]; ERROR_DOTS_SCAN_ROW *curRow = 0; ERROR_DOTS_SCAN_ROW *prevRow = 0; int MIN_AREA = minArea; if (minArea <= 0) { MIN_AREA = 10; } int minEnergy = 2; int mergeDistanceX = 20; int mergeDistanceY = 20; offset = 0; int nErrorType = 0; int lasttype = -1; for (int y = 0; y < height; y++) { wLineErrsList = 0; difSumList = 0; curRow = rowDataTab + (y & 1); curRow->scanCount = 0; offset = y * pitch - 1; nErrorType = -1; lasttype = -1; int kh = 0; for (int x = 0; x < width; x++) { offset++; point_is_err = 0; if (pErrordata[offset] != 0) { point_is_err = 1; difSumList += 1; wLineErrsList++; errPos_xList = x; kh = 1; } else // 没有残点 所有缺陷都需要判断是否截止 { // 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点 if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); wLineErrsList = 0; difSumList = 0; } kh = 0; } if (x == width - 1) { if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); } } } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); prevRow = curRow; } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); ERROR_DOTS_BLOB_PARAM blobParam; memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM)); blobParam.mergeDistance = 1; MergeBlob(blobs, &blobParam); SortBlob(blobs); return 0; } int GetBlobs_V3_CA(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, int width, int height, int minArea, int err_1_value, int err_2_value) { if (blobs == NULL || pErrordata == NULL) { return 1; } int pitch = width; int offset; int point_is_err = 0; int wLineErrsList = 0; int errPos_xList = 0; int difSumList = 0; int point_is_errList = 0; // memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS)); ERROR_DOTS_SCAN_ROW rowDataTab[2]; ERROR_DOTS_SCAN_ROW *curRow = 0; ERROR_DOTS_SCAN_ROW *prevRow = 0; int MIN_AREA = minArea; if (minArea <= 0) { MIN_AREA = 10; } int minEnergy = 2; int mergeDistanceX = 20; int mergeDistanceY = 20; offset = 0; int nErrorType = 0; int lasttype = -1; for (int y = 0; y < height; y++) { wLineErrsList = 0; difSumList = 0; curRow = rowDataTab + (y & 1); curRow->scanCount = 0; offset = y * pitch - 1; nErrorType = -1; lasttype = -1; int kh = 0; for (int x = 0; x < width; x++) { offset++; point_is_err = 0; if (pErrordata[offset] == err_1_value || pErrordata[offset] == err_2_value) { point_is_err = 1; difSumList += 1; wLineErrsList++; errPos_xList = x; kh = 1; } else // 没有残点 所有缺陷都需要判断是否截止 { // 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点 if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); wLineErrsList = 0; difSumList = 0; } kh = 0; } if (x == width - 1) { if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); } } } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); prevRow = curRow; } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); ERROR_DOTS_BLOB_PARAM blobParam; memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM)); blobParam.mergeDistance = 1; MergeBlob(blobs, &blobParam); SortBlob(blobs); return 0; } int GetBlobs_ALL_New(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, unsigned char *pHdata, int width, int height, int minArea) { if (blobs == NULL || pErrordata == NULL || pHdata == NULL) { return 1; } int pitch = width; int offset; int point_is_err = 0; int wLineErrsList[ERR_TYPE_COUNT] = {0}; int errPos_xList[ERR_TYPE_COUNT] = {0}; int difSumList[ERR_TYPE_COUNT] = {0}; memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS)); ERROR_DOTS_SCAN_ROW rowDataTab[2]; ERROR_DOTS_SCAN_ROW *curRow = 0; ERROR_DOTS_SCAN_ROW *prevRow = 0; // int MIN_AREA = 2; int MIN_AREA = minArea; if (minArea <= 0) { MIN_AREA = 10; } int minEnergy = 2; int mergeDistanceX = 25; int mergeDistanceY = 25; offset = 0; int nErrorType = 0; int lasttype = -1; int qx_list[ERR_TYPE_COUNT] = {0}; int kv = 0; for (int y = 0; y < height; y++) { if (kv == 1) { memset(&wLineErrsList, 0, sizeof(int) * ERR_TYPE_COUNT); memset(&difSumList, 0, sizeof(int) * ERR_TYPE_COUNT); } unsigned char *p = pErrordata + y * pitch; curRow = rowDataTab + (y & 1); curRow->scanCount = 0; offset = y * pitch; nErrorType = -1; lasttype = -1; kv = 0; // 表示 这一行缺陷残点 if (pHdata[y]) { for (int x = 0; x < width; x++, p++) { point_is_err = 0; if (*p) { point_is_err = GetType(*p, qx_list); kv = 1; for (int qx_i = 0; qx_i < ERR_TYPE_COUNT; qx_i++) { if (qx_list[qx_i] > 0) { difSumList[qx_i] += 1; wLineErrsList[qx_i]++; errPos_xList[qx_i] = x; } } } else if (kv == 1) // 这一行有残点 { for (int qx_i = 0; qx_i < ERR_TYPE_COUNT; qx_i++) { if (wLineErrsList[qx_i] > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList[qx_i] - wLineErrsList[qx_i] + 1, wLineErrsList[qx_i], y, difSumList[qx_i], 0, 0, qx_i); wLineErrsList[qx_i] = 0; difSumList[qx_i] = 0; } if (!wLineErrsList[ERR_TYPE_1] && !wLineErrsList[ERR_TYPE_2]) { kv = 0; } } } if (x == width - 1) { for (int qx_i = 0; qx_i < ERR_TYPE_COUNT; qx_i++) { if (wLineErrsList[qx_i] > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList[qx_i] - wLineErrsList[qx_i] + 1, wLineErrsList[qx_i], y, difSumList[qx_i], 0, 0, qx_i); } } } // offset++; } } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); prevRow = curRow; } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); ERROR_DOTS_BLOB_PARAM blobParam; memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM)); blobParam.mergeDistance = 1; blobs->srcBlobCount = blobs->blobCount; MergeBlob(blobs, &blobParam); SortBlob(blobs); return 0; } int GetBlobs_oneLabe(ERROR_DOTS_BLOBS *blobs, unsigned char *pErrordata, unsigned char *pHdata, int width, int height, int minArea) { if (blobs == NULL || pErrordata == NULL || pHdata == NULL) { return 1; } int pitch = width; int offset; int point_is_err = 0; int wLineErrsList = 0; int errPos_xList = 0; int difSumList = 0; int point_is_errList = 0; // memset(blobs, 0x00, sizeof(ERROR_DOTS_BLOBS)); ERROR_DOTS_SCAN_ROW rowDataTab[2]; ERROR_DOTS_SCAN_ROW *curRow = 0; ERROR_DOTS_SCAN_ROW *prevRow = 0; int MIN_AREA = minArea; if (minArea <= 0) { MIN_AREA = 10; } int minEnergy = 2; int mergeDistanceX = 20; int mergeDistanceY = 20; offset = 0; int nErrorType = 0; int lasttype = -1; for (int y = 0; y < height; y++) { wLineErrsList = 0; difSumList = 0; curRow = rowDataTab + (y & 1); curRow->scanCount = 0; offset = y * pitch - 1; nErrorType = -1; lasttype = -1; int kh = 0; // 表示 这一行缺陷残点 if (pHdata[y]) { for (int x = 0; x < width; x++) { offset++; point_is_err = 0; if (pErrordata[offset] != 0) { point_is_err = 1; difSumList += 1; wLineErrsList++; errPos_xList = x; kh = 1; } else // 没有残点 所有缺陷都需要判断是否截止 { // 当前点 该缺陷类型 为FALSE 并且 改缺陷类型 有过残点 if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); wLineErrsList = 0; difSumList = 0; } kh = 0; } if (x == width - 1) { if (wLineErrsList > 0) { AddErrorScan_New(curRow, prevRow, errPos_xList - wLineErrsList + 1, wLineErrsList, y, difSumList, 0, 0, ERR_TYPE_1); } } } } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); prevRow = curRow; } LinkScanLineToBlob_New(blobs, prevRow, 0, 0, MIN_AREA, minEnergy, mergeDistanceX, mergeDistanceY, width); ERROR_DOTS_BLOB_PARAM blobParam; memset(&blobParam, 0x00, sizeof(ERROR_DOTS_BLOB_PARAM)); blobParam.mergeDistance = 1; blobs->srcBlobCount = blobs->blobCount; MergeBlob(blobs, &blobParam); SortBlob(blobs); return 0; } int PushBlob(ERROR_DOTS_BLOBS *blobs, ERROR_DOTS_BLOBS *addblobs) { for (int i = 0; i < addblobs->blobCount; i++) { int bhave = 0; for (int j = 0; j < addblobs->blobCount; j++) { if (addblobs->blobTab[i].ErrType == blobs->blobTab[j].ErrType && addblobs->blobTab[i].minx == blobs->blobTab[j].minx && addblobs->blobTab[i].miny == blobs->blobTab[j].miny && addblobs->blobTab[i].maxx == blobs->blobTab[j].maxx && addblobs->blobTab[i].maxy == blobs->blobTab[j].maxy) { bhave = 1; break; } } if (!bhave) { int ncount = blobs->blobCount; if (ncount < _MAX_ERROR_DOT_BLOB) { memcpy(&blobs->blobTab[ncount], &addblobs->blobTab[i], sizeof(ERROR_DOTS_BLOB_DATA)); blobs->blobCount++; } } } return 0; } int CalHJ_Pixel(unsigned char *pErrordata, unsigned char *pMaskdata, int width, int height, int bkvalue, float ratio) { int hjarr[256] = {0}; if (pErrordata == NULL || pMaskdata == NULL) { return 0; } int pitch = width; int offset = 0; int qxcount = 0; for (int y = 0; y < height; y++) { offset = y * pitch; for (int x = 0; x < width; x++) { if (pMaskdata[offset] > 0) { qxcount++; int dv = pErrordata[offset] - bkvalue; if (dv < 0) { dv = -dv; } hjarr[dv]++; } offset++; } } int dstcount = qxcount * ratio; int sum = 0; int usenum = 0; for (int i = 255; i >= 0; i--) { if (dstcount > 0 && hjarr[i] > 0) { sum += i * hjarr[i]; usenum += hjarr[i]; dstcount -= hjarr[i]; } } if (usenum > 0) { return sum / usenum; } return 0; }