doubao_chat/lib/net/turing/tl_imgproc.c

976 lines
32 KiB
C

#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include "printf.h"
typedef struct _IplImageTuling {
int nSize; /**< sizeof(IplImage) */
int nChannels; /**< Most of OpenCV functions support 1,2,3 or 4 channels */
int depth; /**< Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */
int width; /**< Image width in pixels. */
int height; /**< Image height in pixels. */
int imageSize; /**< Image data size in bytes
(==image->height*image->widthStep
in case of interleaved data)*/
unsigned char *imageData; /**< Pointer to aligned image data. */
int widthStep; /**< Size of aligned image row in bytes. */
} IplImageTL;
enum {
TL_CV_GRAY = 0,
TL_CV_RGB = 1,
TL_CV_BGR = 2,
//420
TL_CV_YUV_NV21 = 10,
TL_CV_YUV_NV12 = 11,
TL_CV_YUV_YV12 = 12,
TL_CV_YUV_IYUV = 13,
TL_CV_YUV_I420 = 14,
// 422
TL_CV_YUV_UYVY = 20,
TL_CV_YUV_YUY2 = 21,
TL_CV_YUV_Y422 = 22,
TL_CV_YUV_UYNV = 23,
TL_CV_YUV_YVYU = 24,
TL_CV_YUV_YUYV = 25,
TL_CV_YUV_YUNV = 26
};
typedef enum _TL_IMAGE_TYPE_ {
TL_CV_GRAY2GRAY = 0,
// TL_CV_BGR2RGB = 4,
TL_CV_BGR2GRAY = 6,
TL_CV_RGB2GRAY = 7,
// TL_CV_RGB2BGR = TL_CV_BGR2RGB,
TL_CV_YUV2GRAY_420 = 106,
TL_CV_YUV2GRAY_NV21 = TL_CV_YUV2GRAY_420,
TL_CV_YUV2GRAY_NV12 = TL_CV_YUV2GRAY_420,
TL_CV_YUV2GRAY_YV12 = TL_CV_YUV2GRAY_420,
TL_CV_YUV2GRAY_IYUV = TL_CV_YUV2GRAY_420,
TL_CV_YUV2GRAY_I420 = TL_CV_YUV2GRAY_420,
TL_CV_YUV2GRAY_Y422P = TL_CV_YUV2GRAY_I420,
TL_CV_YUV2GRAY_UYVY = 123,
TL_CV_YUV2GRAY_YUY2 = 124,
TL_CV_YUV2GRAY_Y422 = TL_CV_YUV2GRAY_UYVY,
TL_CV_YUV2GRAY_UYNV = TL_CV_YUV2GRAY_UYVY,
TL_CV_YUV2GRAY_YVYU = TL_CV_YUV2GRAY_YUY2,
TL_CV_YUV2GRAY_YUYV = TL_CV_YUV2GRAY_YUY2,
TL_CV_YUV2GRAY_YUNV = TL_CV_YUV2GRAY_YUY2
} TL_IMAGE_TYPE;
enum {
TL_CV_INTER_NN = 0,
TL_CV_INTER_LINEAR = 1,
TL_CV_INTER_CUBIC = 2,
TL_CV_INTER_AREA = 3,
TL_CV_INTER_LANCZOS4 = 4
};
/** Threshold types */
enum {
TL_CV_THRESH_BINARY = 0, /**< value = value > threshold ? max_value : 0 */
TL_CV_THRESH_BINARY_INV = 1, /**< value = value > threshold ? 0 : max_value */
TL_CV_THRESH_TRUNC = 2, /**< value = value > threshold ? threshold : value */
TL_CV_THRESH_TOZERO = 3, /**< value = value > threshold ? value : 0 */
TL_CV_THRESH_TOZERO_INV = 4, /**< value = value > threshold ? 0 : value */
TL_CV_THRESH_MASK = 7,
TL_CV_THRESH_OTSU = 8, /**< use Otsu algorithm to choose the optimal threshold value;
combine the flag with one of the above CV_THRESH_* values */
TL_CV_THRESH_TRIANGLE = 16 /**< use Triangle algorithm to choose the optimal threshold value;
combine the flag with one of the above CV_THRESH_* values, but not
with CV_THRESH_OTSU */
};
static int cvFloorTL(double value)
{
int i = (int) value;
return i - (i > value);
}
static short saturate_cast_short(float v)
{
return (short)((unsigned long int)((long long int) v - SHRT_MIN) <= (unsigned long int) USHRT_MAX ? v : v > 0
? SHRT_MAX
: SHRT_MIN);
}
// cvCopy
static void cvCopyImageTL(struct _IplImageTuling *src, struct _IplImageTuling *dst)
{
int i = 0, j = 0;
unsigned char *srcPixel;
unsigned char *dstPixel;
if (src->widthStep != dst->widthStep || src->height != dst->height || src->nChannels != dst->nChannels) {
printf("error copyImage shape is different\n");
return;
}
for (i = 0; i < src->height; i++) {
srcPixel = src->imageData + i * src->widthStep;
dstPixel = dst->imageData + i * dst->widthStep;
for (j = 0; j < src->widthStep; j++) {
dstPixel[j] = srcPixel[j];
}
}
}
static unsigned char rgbToGray(const unsigned char R, const unsigned char G, const unsigned char B)
{
unsigned char re;
re = (unsigned char)(((int) R * 19595 + (int) G * 38469 + (int) B * 7472) >> 16);
return re;
}
static void cvBgrToGray(const unsigned char *srcData, unsigned char *dstData, int srcWidthStep, int srcHeight, int srcChannels, int dstWidthStep)
{
int i, j, k;
unsigned char *srcPixel;
unsigned char *dstPixel;
for (i = 0; i < srcHeight; i++) {
srcPixel = (unsigned char *)(srcData + i * srcWidthStep);
dstPixel = (dstData + i * dstWidthStep);
for (j = 0, k = 0; j < srcWidthStep; j += srcChannels, k++) {
// dstPixel[k] = rgbToGray(srcPixel[j + 2], srcPixel[j + 1], srcPixel[j]);
dstPixel[k] = (unsigned char)(
((int) srcPixel[j + 2] * 19595 + (int) srcPixel[j + 1] * 38469 + (int) srcPixel[j] * 7472) >> 16);
}
}
}
static void cvRgbToGray(const unsigned char *srcData, unsigned char *dstData, int srcWidthStep, int srcHeight, int srcChannels, int dstWidthStep)
{
int i, j, k;
unsigned char *srcPixel;
unsigned char *dstPixel;
for (i = 0; i < srcHeight; i++) {
srcPixel = (unsigned char *)(srcData + i * srcWidthStep);
dstPixel = (dstData + i * dstWidthStep);
for (j = 0, k = 0; j < srcWidthStep; j += srcChannels, k++) {
// dstPixel[k] = rgbToGray(srcPixel[j], srcPixel[j + 1], srcPixel[j + 2]);
dstPixel[k] = (unsigned char)(
((int) srcPixel[j] * 19595 + (int) srcPixel[j + 1] * 38469 + (int) srcPixel[j + 2] * 7472) >> 16);
}
}
}
static void cvGrayToGray(const unsigned char *srcData, unsigned char *dstData, int srcWidthStep, int srcHeight)
{
memcpy(dstData, srcData, srcWidthStep * srcHeight);
}
static void cvYuvToGray_420(const unsigned char *srcData, unsigned char *dstData, int srcWidth, int srcHeight)
{
memcpy(dstData, srcData, srcWidth * srcHeight);
}
static void cvYuvToGray_UYVY(const unsigned char *srcData, unsigned char *dstData, int srcHeight, int srcWidth, int dstWidthStep)
{
int i, j, k, y;
unsigned char *srcPixel;
unsigned char *dstPixel;
y = srcWidth * 2;
for (i = 0; i < srcHeight; i++) {
srcPixel = (unsigned char *)(srcData + i * srcWidth * 2);
dstPixel = (dstData + i * dstWidthStep);
for (j = 0, k = 0; j < y; j += 2, k++) {
dstPixel[k] = srcPixel[j + 1];
}
}
}
static void cvYuvToGray_YUYV(const unsigned char *srcData, unsigned char *dstData, int srcHeight, int srcWidth, int dstWidthStep)
{
int i, j, k, y;
unsigned char *srcPixel;
unsigned char *dstPixel;
y = srcWidth * 2;
for (i = 0; i < srcHeight; i++) {
srcPixel = (unsigned char *)(srcData + i * srcWidth * 2);
dstPixel = (dstData + i * dstWidthStep);
for (j = 0, k = 0; j < y; j += 2, k++) {
dstPixel[k] = srcPixel[j];
}
}
}
static void cvRsizeNear(struct _IplImageTuling *src, struct _IplImageTuling *dst)
{
int i, j, k, stepSrc, stepDst;
int sx, sy;
unsigned char *dataDst;
unsigned char *dataSrc;
int n = src->width / dst->width;
stepSrc = src->widthStep;
stepDst = dst->widthStep;
dataSrc = (unsigned char *) src->imageData;
dataDst = (unsigned char *) dst->imageData;
for (i = 0; i < dst->height; i++) {
// sx = cvFloorTL(i * n);
sx = i * n;
sx = sx > (src->height - 1) ? (src->height - 1) : sx;
for (j = 0; j < dst->width; j++) {
// sy = cvFloorTL(j * n);
sy = j * n;
sy = sy > (src->width - 1) ? (src->width - 1) : sy;
for (k = 0; k < src->nChannels; ++k) {
*(dataDst + i * stepDst + src->nChannels * j + k) = (*(dataSrc + sx * stepSrc + sy * src->nChannels + k));
}
}
}
}
static void cvGrayRsizeNear(const unsigned char *dataSrc, int srcWidth, int srcHeight, struct _IplImageTuling *dst)
{
int i, j, k, stepDst, stepSrc = srcWidth, nChannels = 1;
int sx, sy;
unsigned char *dataDst;
int n = srcWidth / dst->width;
stepDst = dst->widthStep;
dataDst = (unsigned char *) dst->imageData;
for (i = 0; i < dst->height; i++) {
sx = i * n;
sx = sx > (srcHeight - 1) ? (srcHeight - 1) : sx;
for (j = 0; j < dst->width; j++) {
sy = j * n;
sy = sy > (srcWidth - 1) ? (srcWidth - 1) : sy;
for (k = 0; k < nChannels; ++k) {
*(dataDst + i * stepDst + nChannels * j + k) = (*(dataSrc + sx * stepSrc + sy * nChannels + k));
}
}
}
}
static void cvHalfRGB(unsigned char *dataSrc, unsigned char *dataDst, int srcHeight, int srcWidth, int srcChannels)
{
//support RGB,GBR,GRAY format
int i, j, k, sx, sy, stepSrc = srcChannels * srcWidth, stepDst = srcChannels * srcWidth / 2;
for (i = 0; i < srcHeight / 2; i++) {
sx = i * 2;
sx = sx > (srcHeight - 1) ? (srcHeight - 1) : sx;
for (j = 0; j < srcWidth / 2; j++) {
sy = j * 2;
sy = sy > (srcWidth - 1) ? (srcWidth - 1) : sy;
for (k = 0; k < srcChannels; ++k) {
*(dataDst + i * stepDst + srcChannels * j + k) = (*(dataSrc + sx * stepSrc + sy * srcChannels + k));
}
}
}
}
static void cvHalfYUV420(unsigned char *dataSrc, unsigned char *dataDst, int srcHeight, int srcWidth)
{
//support YUV420
int i = 0;
for (int y = 0; y < srcHeight; y += 2) {
for (int x = 0; x < srcWidth; x += 2) {
dataDst[i] = dataSrc[y * srcWidth + x];
i++;
}
}
for (int y = 0; y < srcHeight / 2; y += 2) {
for (int x = 0; x < srcWidth; x += 4) {
dataDst[i] = dataSrc[(srcWidth * srcHeight) + (y * srcWidth) + x];
i++;
dataDst[i] = dataSrc[(srcWidth * srcHeight) + (y * srcWidth) + (x + 1)];
i++;
}
}
}
static void cvHalfYUV422(unsigned char *dataSrc, unsigned char *dataDst, int srcHeight, int srcWidth)
{
//support YUV422
int i = 0;
for (int y = 0; y < srcHeight; y += 2) {
for (int x = 0; x < srcWidth; x += 4) {
dataDst[i++] = dataSrc[(y * srcWidth * 2) + x * 2];
dataDst[i++] = dataSrc[(y * srcWidth * 2) + (x * 2 + 1)];
dataDst[i++] = dataSrc[(y * srcWidth * 2) + (x * 2 + 2)];
dataDst[i++] = dataSrc[(y * srcWidth * 2) + (x * 2 + 3)];
}
}
}
static void cvResizeTL(struct _IplImageTuling *src, struct _IplImageTuling *dst, int interpolation)
{
float fy;
int sy;
short cbufy[2];
short cbufx[2];
float fx;
int i, j, k, sx, stepDst, stepSrc, iWidthSrc, iHeightSrc;
unsigned char *dataDst;
unsigned char *dataSrc;
double xRatio;
double yRatio;
xRatio = (double) src->width / dst->width;
yRatio = (double) src->height / dst->height;
dataDst = (unsigned char *) dst->imageData;
dataSrc = (unsigned char *) src->imageData;
stepDst = dst->widthStep;
stepSrc = src->widthStep;
iWidthSrc = src->width;
iHeightSrc = src->height;
i = 0;
j = 0;
k = 0;
for (i = 0; i < dst->height; ++i) {
// float fy = (float) ((1000*i + 500) * yRatio - 500)/1000;
fy = (float)((i + 0.5) * yRatio - 0.5);
sy = (int) fy - ((int) fy > fy);
fy -= sy;
sy = sy < (iHeightSrc - 2) ? sy : (iHeightSrc - 2);
sy = 0 > sy ? 0 : sy;
cbufy[0] = saturate_cast_short(((1.f - fy) * 2048));
cbufy[1] = (short)(2048 - cbufy[0]);
for (j = 0; j < dst->width; ++j) {
fx = (float)((j + 0.5) * xRatio - 0.5);
sx = (int) fx - ((int) fx > fx);
fx -= sx;
if (sx < 0) {
fx = 0, sx = 0;
}
if (sx >= iWidthSrc - 1) {
fx = 0, sx = iWidthSrc - 2;
}
cbufx[0] = saturate_cast_short((1.f - fx) * 2048);
cbufx[1] = (short)(2048 - cbufx[0]);
for (k = 0; k < src->nChannels; ++k) {
*(dataDst + i * stepDst + src->nChannels * j + k) =
(unsigned char)(
((short)(*(dataSrc + sy * stepSrc + src->nChannels * sx + k)) * cbufx[0] * cbufy[0] +
(short)(*(dataSrc + (sy + 1) * stepSrc + src->nChannels * sx + k)) * cbufx[0] * cbufy[1] +
(short)(*(dataSrc + sy * stepSrc + src->nChannels * (sx + 1) + k)) * cbufx[1] * cbufy[0] +
(short)(*(dataSrc + (sy + 1) * stepSrc + src->nChannels * (sx + 1) + k)) * cbufx[1] * cbufy[1]) >> 22);
}
}
}
}
static void cvAbsDiffTL(struct _IplImageTuling *src1, struct _IplImageTuling *src2, struct _IplImageTuling *dst)
{
int i, j, k;
unsigned char *src1Pixel;
unsigned char *src2Pixel;
unsigned char *dstPixel;
if (src1 == NULL || src2 == NULL || dst == NULL) {
printf("tl_error cvAbsDiffTL src1 or src2 or dst is NULL \n");
return;
}
if (src1->widthStep != src2->widthStep || src1->height != src2->height || src1->nChannels != src2->nChannels) {
printf("tl_error cvAbsDiffTL src1 src2 shape is different\n");
return;
}
if (src1->widthStep != dst->widthStep || src1->height != dst->height || src1->nChannels != dst->nChannels) {
printf("tl_error cvAbsDiffTL src1 dst shape is different\n");
return;
}
for (i = 0; i < src1->height; i++) {
src1Pixel = (unsigned char *)(src1->imageData + i * src1->widthStep);
src2Pixel = (unsigned char *)(src2->imageData + i * src2->widthStep);
dstPixel = (unsigned char *) dst->imageData + i * dst->widthStep;
for (j = 0; j < src1->widthStep; j += src1->nChannels) {
for (k = 0; k < src1->nChannels; k++) {
dstPixel[j + k] = (unsigned char)(abs((int) src1Pixel[j + k] - (int) src2Pixel[j + k]));
}
}
}
}
static void cvThresholdTL(struct _IplImageTuling *src, struct _IplImageTuling *dst, double threshold, double max_value,
int threshold_type)
{
int i;
if (src == NULL || dst == NULL) {
printf("tl_error cvThresholdTL src or dst is NULL \n");
return;
}
for (i = 0; i < src->height * src->width * src->nChannels; i++) {
if (TL_CV_THRESH_BINARY == threshold_type) {
if ((int) src->imageData[i] > (int) threshold) {
dst->imageData[i] = (unsigned char)(255);
} else {
dst->imageData[i] = (unsigned char)(0);
}
}
}
}
static void cvErodeTL(struct _IplImageTuling *src, struct _IplImageTuling *dst, int m, int iterations)
{
int x, y, w, h;
unsigned char *srcData;
unsigned char *dstData;
unsigned int t;
int x2, y2, x3, y3;
dstData = (unsigned char *) dst->imageData;
srcData = (unsigned char *) src->imageData;
w = src->width;
h = src->height;
while (iterations-- > 0) {
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
y2 = y - 1;
if (y2 < 0) {
y2 = h - 1;
}
y3 = y + 1;
if (y3 >= h) {
y3 = 0;
}
x2 = x - 1;
if (x2 < 0) {
x2 = w - 1;
}
x3 = x + 1;
if (x3 >= w) {
x3 = 0;
}
t = (unsigned int) srcData[y * w + x];
if ((unsigned int) srcData[y2 * w + x] < t) {
t = (unsigned int) srcData[y2 * w + x];
}
if ((unsigned int) srcData[y3 * w + x] < t) {
t = (unsigned int) srcData[y3 * w + x];
}
if ((unsigned int) srcData[y * w + x2] < t) {
t = (unsigned int) srcData[y * w + x2];
}
if ((unsigned int) srcData[y * w + x3] < t) {
t = (unsigned int) srcData[y * w + x3];
}
dstData[y * w + x] = (unsigned char) t;
}
}
}
}
static void cvCutTL(struct _IplImageTuling *src, struct _IplImageTuling *dst, int targetHeight)
{
int i, j, k, index;
index = 0;
for (i = targetHeight; i < src->height; i++) {
for (j = 0; j < src->width; j++) {
for (k = 0; k < src->nChannels; k++) {
dst->imageData[index] = src->imageData[i * src->widthStep + src->nChannels * j + k];
index ++;
}
}
}
}
#if 0
void printfTL(IplImageTL *src, int type)
{
int i, j;
unsigned char *data;
int step;
int channels;
int sum_all;
int count;
unsigned char *pixel;
unsigned int x_p;
char log_info[8];
printf("printfTL_1\n");
data = (unsigned char *) src->imageData;
step = src->widthStep / sizeof(unsigned char);
channels = src->nChannels;
// uchar b_pixel, g_pixel, r_pixel;
printf("printfTL_2\n");
printf("printfTL_->height:%d\t", src->height);
printf("printfTL_->width:%d\n", src->width);
printf("printfTL_->widthStep:%d\n", src->widthStep);
printf("printfTL_->nChannels:%d\n", src->nChannels);
sum_all = 0;
for (i = 0; i < src->height; i += 1) { // height
count = 0;
for (j = 0; j < src->widthStep; j++) { // width
pixel = (unsigned char *)(src->imageData + i * src->widthStep + j);
x_p = (unsigned int)(*pixel);
if (x_p == 255) {
count += 1;
// printf("%d\t", j);
}
if (type == 1) {
memset(log_info, 0, 8);
sprintf(log_info, "%d", x_p);
// if(j==1279){
// printf("xxx=%s\n",log_info);
// int le = strlen(log_info);
// printf("len=%d\n",le);
// }
write_log_file("ttt.log", log_info, (unsigned int) strlen(log_info));
write_log_file("ttt.log", "\n", (unsigned int)strlen("\n"));
// sprintf(log_info, "%d", x_p);
}
if (j >= src->widthStep - 5) {
printf("\nj=%d\n", j);
}
// printf("i=%d-%dmo\t", j,x_p);
printf("%d\t", x_p);
// if (j >= 60) {
// break;
// }
}
printf("count=%d\t", count);
sum_all += count;
// break;
}
printf("printf_mat_sum_all : %d\n", sum_all);
}
static void write_log_file(const char *filename, const char *buffer, unsigned int buf_size)
{
FILE *fp;
if (filename != NULL && buffer != NULL) {
{
fp = fopen(filename, "w+");
if (fp != NULL) {
fwrite(fp, buffer, buf_size);
fclose(fp);
fp = NULL;
}
}
}
}
#endif
static unsigned char *cvImageTLToUChar(IplImageTL *image, TL_IMAGE_TYPE imageType)
{
int imageSize;
if (image->nChannels == 1) {
imageSize = image->width * image->height;
} else if (imageType == TL_CV_YUV2GRAY_420) {
imageSize = image->width * image->height * 3 / 2;
} else if (imageType == TL_CV_YUV2GRAY_UYVY || imageType == TL_CV_YUV2GRAY_YUY2) {
imageSize = image->width * image->height * 2;
} else {
imageSize = image->width * image->height * image->nChannels + image->width % 4 * image->height;
}
unsigned char *imgData = (unsigned char *)malloc(imageSize);
if (imgData) {
memcpy(imgData, image->imageData, imageSize);
}
// for (int i = 0; i < imageSize; i++) {
// imgData[i] = image->imageData[i];
// }
return imgData;
}
static IplImageTL *cvCreateImageTL(int width, int height, int nChannels, TL_IMAGE_TYPE imageType)
{
IplImageTL *image;
int imageSize;
if (imageType == TL_CV_GRAY2GRAY) {
imageSize = width * height;
} else if (imageType == TL_CV_YUV2GRAY_420) {
imageSize = width * height * 3 / 2;
} else if (imageType == TL_CV_YUV2GRAY_UYVY || imageType == TL_CV_YUV2GRAY_YUY2) {
imageSize = width * height * 2;
} else {
imageSize = width * height * 3 + width % 4 * height;
}
image = (IplImageTL *) malloc(sizeof(IplImageTL));
if (!image) {
return NULL;
}
// printf("imageSize:%d\n", imageSize);
// printf("imageSize:%d\twidth:%d\theight:%d\tnChannels:%d\n", imageSize, width, height, nChannels);
image->imageData = (unsigned char *)malloc(imageSize);
memset(image->imageData, 0, imageSize);
image->width = width;//cols
image->height = height;//rows
image->widthStep = width * nChannels;
image->nChannels = nChannels;
image->imageSize = imageSize;
return image;
}
//unsigned char 转image
static IplImageTL *cvCreateImageTLByUChar(const unsigned char *src, int width, int height, int nChannels, TL_IMAGE_TYPE imageType)
{
int i = 0;
IplImageTL *image;
image = cvCreateImageTL(width, height, nChannels, imageType);
// int allSize = width * height * nChannels;
// printf("allSize:%d\twidth:%d\theight:%d\tnChannels:%d\n", allSize, width, height, nChannels);
// for (i = 0; i < image->imageSize; i++) {
// image->imageData[i] = src[i];
// }
if (image) {
memcpy(image->imageData, src, image->imageSize);
}
return image;
}
static void cvtColorTL(struct _IplImageTuling *src, struct _IplImageTuling *dst, TL_IMAGE_TYPE code)
{
unsigned char *srcData;
unsigned char *dstData;
int srcWidthStep = src->widthStep;
int srcHeight = src->height;
int srcChannel = src->nChannels;
int srcWidth = src->width;
int dstWidthStep = dst->widthStep;
srcData = (unsigned char *) src->imageData;
dstData = (unsigned char *) dst->imageData;
if (code == TL_CV_RGB2GRAY) {
cvRgbToGray(srcData, dstData, srcWidthStep, srcHeight, srcChannel, dstWidthStep);
} else if (code == TL_CV_BGR2GRAY) {
cvBgrToGray(srcData, dstData, srcWidthStep, srcHeight, srcChannel, dstWidthStep);
} else if (TL_CV_GRAY2GRAY == code) {
cvGrayToGray(srcData, dstData, srcWidthStep, srcHeight);
} else if (code == TL_CV_YUV2GRAY_420) {
memcpy(dstData, srcData, srcWidth * srcHeight);
// cvYuvToGray_420(srcData, dstData, srcWidth, srcHeight);
} else if (code == TL_CV_YUV2GRAY_UYVY) {
cvYuvToGray_UYVY(srcData, dstData, srcHeight, srcWidth, dstWidthStep);
} else if (code == TL_CV_YUV2GRAY_YUYV) {
cvYuvToGray_YUYV(srcData, dstData, srcHeight, srcWidth, dstWidthStep);
}
}
static IplImageTL *cvCreateImageGRAYTLByUChar(const unsigned char *srcData, int srcWidth, int srcHeight, int srcChannel, TL_IMAGE_TYPE code)
{
int srcWidthStep = srcWidth * srcChannel;
IplImageTL *imageGray = cvCreateImageTL(srcWidth, srcHeight, 1, code);
if (!imageGray) {
return NULL;
}
unsigned char *dstData = (unsigned char *)imageGray->imageData;
int dstWidthStep = imageGray->widthStep;
if (code == TL_CV_RGB2GRAY) {
cvRgbToGray(srcData, dstData, srcWidthStep, srcHeight, srcChannel, dstWidthStep);
} else if (code == TL_CV_BGR2GRAY) {
cvBgrToGray(srcData, dstData, srcWidthStep, srcHeight, srcChannel, dstWidthStep);
} else if (TL_CV_GRAY2GRAY == code) {
cvGrayToGray(srcData, dstData, srcWidthStep, srcHeight);
} else if (code == TL_CV_YUV2GRAY_420) {
memcpy(dstData, srcData, srcWidth * srcHeight);
// cvYuvToGray_420(srcData, dstData, srcWidth, srcHeight);
} else if (code == TL_CV_YUV2GRAY_UYVY) {
cvYuvToGray_UYVY(srcData, dstData, srcHeight, srcWidth, dstWidthStep);
} else if (code == TL_CV_YUV2GRAY_YUYV) {
cvYuvToGray_YUYV(srcData, dstData, srcHeight, srcWidth, dstWidthStep);
}
return imageGray;
}
void cvFreeImageTL(void *ptr)
{
struct _IplImageTuling *image = (struct _IplImageTuling *)ptr;
if (image != NULL) {
free(image->imageData);
free(image);
}
}
typedef struct _MotionDetection_ {
int dstHeight;
int min_thr;
int max_thr;
int minThrWaitTime;
int fps;
int number_of_changes;
int state; // 0-before max thr 1-after max thr 2 after min thr
int sever_wait_state;
int send_state;
int cropRate;
int serverWaitTime;
int lastSend;
int lossFrame;
int lossFrameThr;
long long compareTimer;
long long lastTimer;
long long lastMdTimer;
IplImageTL *frame1;
// int isMove;
// int outputImgHeight;
// int outputImgWidth;
// int outputImgChannels;
// unsigned char * outputImgData;
} MotionDetection;
static void setUserMode(MotionDetection *md, int ocrFlag, int fingerFlag)
{
if (fingerFlag) {
md->cropRate = 0;
}
if (fingerFlag && ocrFlag) {
md->max_thr = 15;
md->min_thr = 5;
} else if (fingerFlag && !ocrFlag) {
md->max_thr = 45;
md->min_thr = 20;
} else if (!fingerFlag && ocrFlag) {
md->max_thr = 60;
md->min_thr = 5;
} else if (!fingerFlag && !ocrFlag) {
md->max_thr = 60;
md->min_thr = 20;
}
}
void initMotionDetection(MotionDetection *md, int min_thr, int max_thr, int minThrWaitTime, int dstHeight, int cropRate,
int serverWaitTime, int timer, long long nowTime)
{
// int frameThr;
md->min_thr = min_thr * (100 - cropRate) / 100;
md->max_thr = max_thr * (100 - cropRate) / 100;
md->minThrWaitTime = minThrWaitTime;
md->fps = 5;
md->dstHeight = dstHeight;
md->cropRate = cropRate;
// frameThr = md->minThrWaitTime * fps / 1000;
// md->send_state = 2 + (1 < frameThr ? 1 : frameThr);
md->send_state = 2;
md->number_of_changes = 0;
md->state = 0;
md->sever_wait_state = 0;
md->serverWaitTime = serverWaitTime;
md->lastSend = 0;
md->lossFrame = md->fps / md->fps;
md->lossFrameThr = 1;
md->compareTimer = timer;
md->lastTimer = nowTime + md->compareTimer;
md->lastMdTimer = nowTime + md->serverWaitTime;
md->frame1 = NULL;
}
static void getDifference(MotionDetection *md, IplImageTL *motion)
{
int i = 0, j = 0;
unsigned char *pixel_x;
int pixel;
for (j = 0; j < motion->height; j++) { // height
for (i = 0; i < motion->width; i++) { // width
pixel_x = (unsigned char *)(motion->imageData + j * motion->widthStep + i);
pixel = (*pixel_x) + 0;
if (pixel == 255) {
md->number_of_changes++;
}
}
}
}
static void updateState(MotionDetection *md)
{
if (md->state >= md->send_state && md->lastSend == 1) {
md->state = 0;
}
if (md->state == 0 && md->number_of_changes > md->max_thr) {
md->state = 1;
} else if (md->state == 1 && md->number_of_changes < md->min_thr) {
md->state = 2;
} else if (md->state >= 2) {
if (md->number_of_changes < md->min_thr) {
md->state += 1;
} else {
md->state = 1;
}
}
}
static void imageCompare(MotionDetection *md, IplImageTL *frame2)
{
IplImageTL *temp;
IplImageTL *motion;
motion = cvCreateImageTL(md->frame1->width, md->frame1->height, md->frame1->nChannels, TL_CV_RGB2GRAY);
cvAbsDiffTL(md->frame1, frame2, motion);
cvThresholdTL(motion, motion, 35, 255, TL_CV_THRESH_BINARY);
temp = cvCreateImageTL(motion->width, motion->height, motion->nChannels, TL_CV_RGB2GRAY);
cvCopyImageTL(motion, temp);
memset(motion->imageData, 0, motion->width * motion->height);
cvErodeTL(temp, motion, 0, 1);
cvFreeImageTL(temp);
getDifference(md, motion);
cvFreeImageTL(motion);
}
static void detectMotion(MotionDetection *md, IplImageTL *frame, TL_IMAGE_TYPE imageType)
{
int cutHeight;
int flag = 0;
cutHeight = frame->height * md->cropRate / 100;
cvCutTL(frame, frame, cutHeight);
frame->height = frame->height - cutHeight;
md->number_of_changes = 0;
if (md->frame1 == NULL) {
// first
cvFreeImageTL(md->frame1);
md->frame1 = cvCreateImageTL(frame->width, frame->height, frame->nChannels, imageType);
cvCopyImageTL(frame, md->frame1);
flag = 1;
} else if (md->frame1->width != frame->width || md->frame1->height != frame->height) {
cvFreeImageTL(md->frame1);
md->frame1 = cvCreateImageTL(frame->width, frame->height, frame->nChannels, imageType);
cvCopyImageTL(frame, md->frame1);
flag = 1;
}
if (frame->width != md->frame1->width || frame->height != md->frame1->height) {
printf("error 101 frame1 frame2 shape is diff \n");
cvFreeImageTL(frame);
cvFreeImageTL(md->frame1);
return;
}
imageCompare(md, frame);
if (flag == 0 && md->frame1->imageData != NULL) {
cvFreeImageTL(md->frame1);
md->frame1 = cvCreateImageTL(frame->width, frame->height, frame->nChannels, imageType);
cvCopyImageTL(frame, md->frame1);
}
updateState(md);
}
int getNumOfChanges(MotionDetection *md)
{
return md->number_of_changes;
}
static unsigned char *getOutImgData(unsigned char *image, TL_IMAGE_TYPE imageType, int srcHeight, int srcWidth, int ocrFlag)
{
unsigned char *outData = NULL;
if (!ocrFlag) {
if (imageType == TL_CV_YUV2GRAY_420) {
//outData = (unsigned char*)malloc(srcHeight/2 * srcWidth/2 * 3/2);
#if 1
cvHalfYUV420(image, image, srcHeight, srcWidth);
#else
extern int YUV420p_Soft_Scaling(unsigned char *src, unsigned char *out, int src_w, int src_h, int out_w, int out_h);
YUV420p_Soft_Scaling(image, image, srcWidth, srcHeight, srcWidth / 2, srcHeight / 2);
#endif
outData = image;
} else if (imageType == TL_CV_YUV2GRAY_UYVY || imageType == TL_CV_YUV2GRAY_YUY2) {
cvHalfYUV422(image, image, srcHeight, srcWidth);
outData = image;
} else if (imageType == TL_CV_BGR2GRAY || imageType == TL_CV_RGB2GRAY) {
//outData = (unsigned char*)malloc(srcHeight/2 * srcWidth/2 * 3);
cvHalfRGB(image, image, srcHeight, srcWidth, 3);
outData = image;
} else if (imageType == TL_CV_GRAY2GRAY) {
//outData = (unsigned char*)malloc(srcHeight/2 * srcWidth/2);
cvHalfRGB(image, image, srcHeight, srcWidth, 1);
outData = image;
} else {
outData = NULL;
}
} else {
outData = image;
}
return outData;
}
static int checkCode(int width, int height, int channels, long long nowTime, int ocrFlag, int fingerFlag, int chekCode)
{
int code = 0;
int sumAll = channels + ocrFlag + fingerFlag;
while (width != 0) {
sumAll += width % 10;
width /= 10;
}
while (height != 0) {
sumAll += height % 10;
height /= 10;
}
while (nowTime != 0) {
sumAll += nowTime % 10;
nowTime /= 10;
}
sumAll *= 23;
code = sumAll % 256;
if (code == chekCode) {
return 1;
} else {
return 0;
}
}
unsigned char *getMotionResult(MotionDetection *md, const unsigned char *image, int width, int height, int channels,
TL_IMAGE_TYPE imageType, long long nowTime, int ocrFlag, int fingerFlag)
{
if (nowTime - md->lastTimer < md->compareTimer) {
return NULL;
}
md->lastTimer = nowTime;
IplImageTL *dstImageGRAY;
unsigned char *outputImgData = NULL;
setUserMode(md, ocrFlag, fingerFlag);
//dstImageGRAY use for detection
dstImageGRAY = cvCreateImageTL(md->dstHeight * width / height, md->dstHeight, 1, TL_CV_GRAY2GRAY);
//if image is YUV420 format, get gray image easy
if (imageType == TL_CV_YUV2GRAY_420) {
cvGrayRsizeNear(image, width, height, dstImageGRAY);
} else {
//if image is not YUV420 format , we need malloc zone to get gray image
IplImageTL *imageGRAY;
imageGRAY = cvCreateImageGRAYTLByUChar(image, width, height, channels, imageType);
cvRsizeNear(imageGRAY, dstImageGRAY);
cvFreeImageTL(imageGRAY);
}
detectMotion(md, dstImageGRAY, TL_CV_GRAY2GRAY);
//return image imageType is same as input image
int isMove = md->state >= md->send_state;
if (isMove > 0 && nowTime - md->lastMdTimer >= (long long) md->serverWaitTime) {
md->lastMdTimer = nowTime;
md->lastSend = 1;
outputImgData = getOutImgData((unsigned char *)image, imageType, height, width, ocrFlag);
} else {
md->lastSend = 0;
}
cvFreeImageTL(dstImageGRAY);
return outputImgData;
}