#include "Export.h" // 将图像转成所需的灰度图,且进行缩放 bool ConvertImage(const char* srcImgData, int imgwidth, int imgheight, ColorType colorType, int newW, int newH, const char* dstImgData) { try { // 检查通道数 if (colorType != Gray8 && colorType != Rgb && colorType != Bgr && colorType != Bgra && colorType != Rgba) { //ErrorMsg::SetErrorMsg(ConvertError, { "unexpected colorType." }); return false; } // 检查图像尺寸 if (imgwidth <= 0 || imgheight <= 0) { //ErrorMsg::SetErrorMsg(ConvertError, { "unexpected image size." }); return false; } // 检查指针 if (srcImgData == nullptr) { //ErrorMsg::SetErrorMsg(ConvertError, { "unexpected image data pointer." }); return false; } cv::Size imgSize = cv::Size(imgwidth, imgheight); cv::Mat img; cv::Mat imgGray = cv::Mat(imgSize, CV_8UC1); switch (colorType) { case Gray8: img = cv::Mat(imgSize, CV_8UC(1), (void*)srcImgData); imgGray = img.clone(); break; case Rgb: img = cv::Mat(imgSize, CV_8UC(3), (void*)srcImgData); cvtColor(img, imgGray, cv::COLOR_RGB2GRAY); break; case Bgr: img = cv::Mat(imgSize, CV_8UC(3), (void*)srcImgData); cvtColor(img, imgGray, cv::COLOR_BGR2GRAY); break; case Rgba: img = cv::Mat(imgSize, CV_8UC(4), (void*)srcImgData); cvtColor(img, imgGray, cv::COLOR_RGBA2GRAY); break; case Bgra: img = cv::Mat(imgSize, CV_8UC(4), (void*)srcImgData); cvtColor(img, imgGray, cv::COLOR_BGRA2GRAY); break; } img.release(); cv::Size newSize = cv::Size(newW, newH);//cvSize(120, 120); cv::Mat imgResized; cv::resize(imgGray, imgResized, newSize); imgGray.release(); ; // 去除椒盐噪声 cv::medianBlur(imgResized, imgResized, 5); memcpy((void*)dstImgData, imgResized.data, sizeof(char) * newW * newH); imgResized.release(); return true; } catch (const std::exception& ex) { //ErrorMsg::SetErrorMsg(ConvertError, { ex.what() }); return false; } } // 对图像进行canny运算,计算得到的边缘所占的比值 bool ProcessOneImage(const char* imgData, int imgwidth, int imgheight, ColorType colorType, double& cannyRatio) { try { // 检查通道数 if (colorType != Gray8 && colorType != Rgb && colorType != Bgr && colorType != Bgra && colorType != Rgba) { //ErrorMsg::SetErrorMsg(CannyError, { "unexpected colorType." }); return false; } // 检查图像尺寸 if (imgwidth <= 0 || imgheight <= 0) { //ErrorMsg::SetErrorMsg(CannyError, { "unexpected image size." }); return false; } // 检查指针 if (imgData == nullptr) { //ErrorMsg::SetErrorMsg(CannyError, { "unexpected image data pointer." }); return false; } int channel = 1; switch (colorType) { case Gray8: channel = 1; break; case Rgb: case Bgr: channel = 3; break; case Rgba: case Bgra: channel = 4; break; } // 复制图像 cv::Size imgSize = cv::Size(imgwidth, imgheight); cv::Mat img = cv::Mat(imgSize, CV_8UC(channel)); memcpy(img.data, imgData, imgwidth * imgheight * channel); // 计算canny系数 cannyProcess(img, cannyRatio); return true; } catch (const std::exception& ex) { //ErrorMsg::SetErrorMsg(CannyError, { ex.what() }); return false; } } // 根据累积的一些信息,判断当前图像的状态 CurrentVideoState JudgeImage(double* diffData, double* corrData, double* cannyData, int num, int movingDelayNum, int stationaryDelayNum, int movingDelayTriggerNum, int stationaryDelayTriggerNum, bool manuallyUnfreeze, ExtendState& state) { try { double diffVar = 0; double cannyVar = 0; CurrentVideoState tmp = Notjudged; std::vector vDiffData; std::vector vCannyData; for (int i = 0; i < num; i++) { vDiffData.push_back(diffData[i]); vCannyData.push_back(cannyData[i]); } if (vDiffData.size() > 1) { varVector(vDiffData, diffVar); cannyVector(vCannyData, cannyVar); if ((diffVar > 100 && cannyVar > 0.8) || cannyVar > 2.5) { tmp = Moving; } else if (diffVar < 20 || cannyVar < 0.5) { tmp = Stationary; } else { tmp = Notjudged; } } else { tmp = Stationary; } if (tmp != Notjudged) { if (tmp == Stationary) { // 如果之前是强制延长Stationary状态,现在已经是真实的判为是静置了,可以把状态量恢复了 if (state.StationaryExtendedState) { state.StationaryExtendedNum = 0; state.StationaryExtendedState = false; } if (state.TrueMovingNum > movingDelayTriggerNum || manuallyUnfreeze) { state.MovingExtendedState = true; } if (state.MovingExtendedState) { if (state.MovingExtendedNum < movingDelayNum) { state.MovingExtendedNum++; return Moving; } // 延迟帧数已经超标,清空状态 state.TrueMovingNum = 0; state.MovingExtendedNum = 0; state.MovingExtendedState = false; } // 如果之前不是静置,则TrueStationary的计数清零 if (state.LastState) { state.TrueStationaryNum = 0; } state.TrueStationaryNum++; state.LastState = false; return Stationary; } else if (tmp == Moving) { // 如果之前是强制延长Moving状态,现在已经是真实的判为是扫查中了,可以把状态量恢复了 if (state.MovingExtendedState) { state.MovingExtendedNum = 0; state.MovingExtendedState = false; } if (state.TrueStationaryNum > stationaryDelayTriggerNum) { state.StationaryExtendedState = true; } if (state.StationaryExtendedState) { if (state.StationaryExtendedNum < stationaryDelayNum) { state.StationaryExtendedNum++; return Stationary; } // 超过限定个数,清空 state.TrueStationaryNum = 0; state.StationaryExtendedNum = 0; state.StationaryExtendedState = false; } // 如果之前不是运行,则TrueMoving的计数清零 if (!state.LastState) { state.TrueMovingNum = 0; } state.TrueMovingNum++; state.LastState = true; return Moving; } } else { if (state.LastState) { return Moving; } else { return Stationary; } } } catch (const std::exception& ex) { //ErrorMsg::SetErrorMsg(JudgeError, { ex.what() }); return HaveError; } } // 对两幅图像进行互相关计算 double CompareTwoImage(const char* pSrc1, const char* pSrc2, int width, int height, int widthstep, double& corr, double& diff) { try { double ratio = 0; // 求两幅图的互相关系数 calcorrcoef((uint8_t*)(pSrc1), (uint8_t*)(pSrc2), width, height, widthstep, corr); // corr大于该值,则认为两幅图可能一致,不计算diff(默认为0) // corr小于该值,可计算两幅图的差异 if (corr < 0.999) { ratio = calDiff((uint8_t*)(pSrc1), (uint8_t*)(pSrc2), width, height, diff); } return ratio; } catch (const std::exception& ex) { //ErrorMsg::SetErrorMsg(ImageDiffError, { ex.what() }); return 2; } } // 图像数据解码 bool ImgDataDecode(const uint8_t* srcImgData, const int srcDataSize, ImreadModes imReadMode, ImageInfo* imageInfo) { std::vector dataDecode; dataDecode.resize(srcDataSize); for (int ni = 0; ni < srcDataSize; ni++) { dataDecode[ni] = srcImgData[ni]; } cv::Mat imgDecode = cv::imdecode(dataDecode, imReadMode); imageInfo->width = imgDecode.cols; imageInfo->height = imgDecode.rows; auto type = imgDecode.type(); switch (type) { case CV_8UC1: imageInfo->colorType = Gray8; break; case CV_8UC3: imageInfo->colorType = Bgr; break; case CV_8UC4: imageInfo->colorType = Bgra; break; default: return false; } return true; } // 获得解码后的图像尺寸 int GetDecodedImgSize(const uint8_t* srcImgData, const int srcDataSize, ImreadModes imReadMode) { std::vector dataDecode; dataDecode.resize(srcDataSize); for (int ni = 0; ni < srcDataSize; ni++) { dataDecode[ni] = srcImgData[ni]; } cv::Mat imgDecode = cv::imdecode(dataDecode, imReadMode); auto total = imgDecode.total(); auto elemSize = imgDecode.elemSize(); return total * elemSize; }