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
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;
|
|
}
|