You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1009 lines
26 KiB

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;t<MAX_MACRO_COUNT;t++)
//{
// //curRow->macro[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;t<MAX_MACRO_COUNT;t++)
//{
// //curRow->macro[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;
}