给LUA脚本插上图像识别翅膀
2020-04-29 18:29
791 查看
给LUA脚本插上图像识别翅膀
DrGraph QQ:282397369
前言
这个春节一直猫在家,不给政府添乱。今天是元宵节,正想出去一趟,微信群看到一条信息,立马就不动了:今天千万不要外出,不然会被病毒笑话的:原来你们躲得过初一,躲不过十五。 那就先把这个十五躲过去,继续宅。
废话少说,其实我用LUA也就是点皮毛。就用这点皮毛扎个小辫,给LUA提供图像识别功能
准备知识
- C++与LUA交互,这个在网上一抓一大把
- 基于C++与LUA的分工,需要首先在C++端提供图像识别的各项功能。我用OpenCV实现图像识别功能。
思路
LUA端类实现
以类的方式实现LUA端的调用代码,最终实现一个drMAT类,并创建一个实例cv。如下代码【后续持续完善,以实现更多功能】
drMAT = class() cv = drMAT.new() function drMAT:ctor() end function drMAT:MatFromFile(fileName, destMat) return drMAT_MatFromFile(fileName, cbw(destMat)) end function drMAT:SaveMat(mat, fileName) return drMAT_SaveMat(mat, fileName) end function drMAT:SubMat(mat, rect, destMat, desc) return drMAT_SubMat(mat, rect, cbw(destMat), cbw(desc)) end function drMAT:Convert(mat, method, destMat, desc) return drMAT_Convert(mat, method, cbw(destMat), cbw(desc)) end function drMAT:ToMat_MASK(mat, method, destMat, desc) return drMAT_ToMat_MASK(mat, method, cbw(destMat), cbw(desc)) end function drMAT:Bitwise(mat, bitType, mat2, destMat, desc) return drMAT_Bitwise(mat, bitType, cbw(mat2), cbw(destMat), cbw(desc)) end function drMAT:Filter(mat, filterContent, destMat, desc) return drMAT_Filter(mat, cbw(filterContent), cbw(destMat), cbw(desc)) end function drMAT:GetPosition(mat, subMat, index) return drMAT_GetPosition(mat, subMat, cbw(index, "0")) end function drMAT:GetFeature(mat, featureName) return drMAT_GetFeature(mat, featureName) end function drMAT:countNonZero(mat, destMat) return drMAT_countNonZero(mat, cbw(destMat)) end function drMAT:resize(mat, size, destMat, desc) return drMAT_resize(mat, size, cbw(destMat), cbw(desc)) end function drMAT:GetIcon(mat, mask, iconSize, index, destMat, desc) return drMAT_GetIcon(mat, mask, iconSize, cbw(index, "0"), cbw(destMat), cbw(desc)) end function drMAT:FillMat(mat, value, rect, desc) return drMAT_FillMat(mat, value, cbw(rect, "(0, 0, 0, 0)"), cbw(desc)) end
LUA端调用
直接调用实例对象的方法函数即可。
如要取得某Mat子图,直接调用mat = cv:SubMat(mat, “86, 712, 1120, 4”)
C++端实现
主要是响应相应的LUA调用
bool __fastcall TDrGraphScriptManager::OnLuaRequest_MAT(TDrLUA * lua, UnicodeString funName, TStrings * params) { int paramIndex = 0; UnicodeString firstParam = THelper::GetLuaParamAt(params, paramIndex++); if(IsSame(L"drMAT_MatFromFile", funName)) { UnicodeString fileName = lua->ParseFileName(firstParam); cv::Mat mat = CvHelper::EmptyMat(); if(FileExists(fileName)) mat = CvHelper::MatFromFile(fileName); lua->AddReturnValue(mat, NextTwoParam(params, paramIndex), "文件读入图像"); } else if(THelper::String::IsStartWith(funName, L"drMAT_")) { // 以下首参为图像对象 cv::Mat srcMat = lua->ParseMat(firstParam); cv::Mat resultMat = CvHelper::EmptyMat(); if(srcMat.empty()) { funName.Delete(1, 6); lua->LogWarning(THelper::FormatString(L"第 %d 行警告:ApiMat调用%s函数时,待处理图像对象(第一个参数)为空,请检查!", lua->CurrentLine, funName)); return false; } if(IsSame(L"drMAT_SaveMat", funName)) { UnicodeString fileName = lua->ParseFileName(THelper::GetLuaParamAt(params, paramIndex++), !FILE_MUST_EXISTED); CvHelper::MatToFile(srcMat, fileName); } else if(IsSame(L"drMAT_SubMat", funName)) { cv::Rect rect = lua->ParseRect(THelper::GetLuaParamAt(params, paramIndex++)); resultMat = CvHelper::CopySubMat(srcMat, rect); lua->AddReturnValue(resultMat, NextTwoParam(params, paramIndex), "子图"); } else if(IsSame(L"drMAT_FillMat", funName)) { BYTE value = TTypeConvert::Str2Int(THelper::GetLuaParamAt(params, paramIndex++)); cv::Rect rect = lua->ParseRect(THelper::GetLuaParamAt(params, paramIndex++)); cv::Mat dstMat = srcMat; if(rect.width > 0) { CvHelper::ConstraintRect(rect, srcMat); dstMat = srcMat(rect); } CvHelper::FillMat(dstMat, value); resultMat = srcMat; lua->AddReturnValue(resultMat, firstParam + THelper::GetLuaParamAt(params, paramIndex++, L""), "填充图像"); } else if(IsSame(L"drMAT_Convert", funName)) { UnicodeString method = THelper::GetLuaParamAt(params, paramIndex++); UnicodeString desc = L"转换图像"; if(IsSame(L"Gray", method)) { resultMat = CvHelper::ToMat_GRAY(srcMat); desc = L"灰度图"; } else if(IsSame(L"GrayMAX", method)) { resultMat = CvHelper::ToMat_MaxGRAY(srcMat); desc = L"最大灰度图"; } else if(IsSame(L"GrayMin", method)) { resultMat = CvHelper::ToMat_MinGRAY(srcMat); desc = L"最小灰度图"; } else if(IsSame(L"WhiteBackground", method)) { cv::Mat foreMaskMat = GetForeMat(srcMat); resultMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type()); CvHelper::FillMat(resultMat, 0xFF); srcMat.copyTo(resultMat, foreMaskMat); desc = L"白色背景图"; } else if(method.Pos(L"=")) { UnicodeString name = THelper::String::GetStringAt(method, L"=", 0).Trim(); UnicodeString value = THelper::String::GetStringAt(method, L"=", 1).Trim(); if(IsSame(L"threshold", name)) { BYTE thresValue = TTypeConvert::Str2Int(value); threshold(srcMat, resultMat, thresValue, 0xFF, cv::THRESH_BINARY); desc = L"二值图"; } else if(IsSame(L"ratio", name)) { double ratio = value.ToDouble(); if(ratio > 0) resize(srcMat, resultMat, cv::Size(srcMat.cols * ratio, srcMat.rows * ratio)); desc = L"缩放图"; } else if(IsSame(L"Background", name)) { cv::Mat foreMaskMat = GetForeMat(srcMat); cv::Mat foreSrcMat = srcMat.clone(); BYTE bkValue = TTypeConvert::Str2Int(THelper::String::GetStringAt(value, L",", 0).Trim()); resultMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type()); CvHelper::FillMat(resultMat, bkValue); UnicodeString foreValue = THelper::String::GetStringAt(value, L",", 1).Trim(); if(foreValue.Length()) { bkValue = TTypeConvert::Str2Int(foreValue); CvHelper::FillMat(foreSrcMat, bkValue); } foreSrcMat.copyTo(resultMat, foreMaskMat); } } else if(method.LowerCase().Pos(L"threshold") == 1) { BYTE thresValue = TTypeConvert::Str2Int(THelper::String::GetStringAt(method, L"=", 1)); threshold(srcMat, resultMat, thresValue, 0xFF, cv::THRESH_BINARY); desc = L"二值图"; } else if(method.LowerCase().Pos(L"ratio") == 1) { double ratio = THelper::String::GetStringAt(method, L"=", 1).Trim().ToDouble(); if(ratio > 0) resize(srcMat, resultMat, cv::Size(srcMat.cols * ratio, srcMat.rows * ratio)); desc = L"缩放图"; } lua->AddReturnValue(resultMat, NextTwoParam(params, paramIndex), desc); } else if(IsSame(L"drMAT_Bitwise", funName)) { UnicodeString type = THelper::GetLuaParamAt(params, paramIndex++); if(IsSame(L"not", type)) { bitwise_not(srcMat, resultMat); } else { cv::Mat mat2 = lua->ParseMat(THelper::GetLuaParamAt(params, paramIndex++)); if(IsSame(L"and", type)) bitwise_and(srcMat, mat2, resultMat); else if(IsSame(L"or", type)) bitwise_or(srcMat, mat2, resultMat); else if(IsSame(L"xor", type)) bitwise_xor(srcMat, mat2, resultMat); } lua->AddReturnValue(resultMat, NextTwoParam(params, paramIndex), THelper::FormatString(L"%s位操作结果图", type)); } else if(IsSame(L"drMAT_Filter", funName)) { UnicodeString filterContent = THelper::GetLuaParamAt(params, paramIndex++); UnicodeString filterName = THelper::String::GetStringAt(filterContent, L";").Trim(); THelper::String::EnsureWithStart(filterName, L"TFilter_"); TFilterBase * filter = NewFilterByType(filterName); if(filter) { int count = THelper::String::SplitNumber(filterContent, L";"); for(int i = 1; i < count; ++i) { UnicodeString param = THelper::String::GetStringAt(filterContent, L";", i).Trim(); int index = THelper::String::GetStringAt(param, L"=", 0).ToInt(); param = THelper::String::GetStringAt(param, L"=", 1).Trim(); double value = THelper::String::GetStringAt(param, L",", 0, true, L"0").ToDouble(); double ratio = THelper::String::GetStringAt(param, L",", 1, true, L"1").ToDouble(); filter->SetValue(index, value, ratio); } resultMat = srcMat.clone(); filter->FilterProcess(resultMat); delete filter; } lua->AddReturnValue(resultMat, NextTwoParam(params, paramIndex), THelper::FormatString(L"%s滤镜结果图", filterName)); } else if(IsSame(L"drMAT_GetPosition", funName)) { UnicodeString subMatContent = THelper::GetLuaParamAt(params, paramIndex++); TPoint resultPos(-1, -1); if(subMatContent.Pos(L"<<")) { TPositionOption option; option.ReadFromString(subMatContent); CvRects allRects = CvHelper::UIParse_GetEdit(srcMat, option); int size = allRects.size(); UnicodeString indexText = THelper::GetLuaParamAt(params, paramIndex++, L"0").Trim().LowerCase(); int index = indexText.ToInt(); if(index < 0) index += size; if(IS_IN_RANGE(index, 0, size - 1)) { CvRect r = allRects[index]; resultPos = TPoint(r.x + r.width / 2, r.y + r.height / 2); } } else if(THelper::String::IsStartWith(subMatContent.LowerCase(), L"icon")) { UnicodeString iconName = THelper::String::GetStringAt(subMatContent, L"=", 1).Trim(); cv::Mat iconMat = lua->ParseMat(iconName); cv::Mat whiteBkMat = GetWhiteBackgroundMat(srcMat); cv::Mat maskMat = CvHelper::BuildTransMaskMat(whiteBkMat, clWhite, 5); bitwise_not(maskMat, maskMat); CvRects rects = GetIconRects(maskMat, iconMat.cols, iconMat.rows); CBW_ITERATOR(CvRects, rects) { cv::Mat dstMat = CvHelper::CopySubMat(whiteBkMat, *it); if(CvHelper::IsSameIcons(dstMat, iconMat, false, true, 0.90, false, 3, false, false)) { resultPos = TPoint(it->x + it->width / 2, it->y + it->height / 2); break; } } } else { UnicodeString fileName = lua->ParseFileName(subMatContent, !FILE_MUST_EXISTED); cv::Mat subMat; if(FileExists(fileName)) subMat = CvHelper::MatFromFile(fileName); else subMat = lua->ParseMat(subMatContent); if(!subMat.empty()) resultPos = CvHelper::GetSubMatPos(srcMat, subMat); } lua->AddReturnValue(resultPos); } else if(IsSame(L"drMAT_ToMat_MASK", funName)) { UnicodeString method = THelper::GetLuaParamAt(params, paramIndex++); UnicodeString type = THelper::String::GetStringAt(method, L",", 0).Trim(); UnicodeString value1 = THelper::String::GetStringAt(method, L",", 1).Trim(); UnicodeString value2 = THelper::String::GetStringAt(method, L",", 2).Trim(); int v1 = TTypeConvert::Str2Int(value1); if(IsSame(L"Color", type)) { if(value2.Length()) { int delta = TTypeConvert::Str2Int(value2); resultMat = CvHelper::BuildTransMaskMat(srcMat, TColor(v1), delta); } else resultMat = CvHelper::BuildTransMaskMat_ColorPass(srcMat, v1); } else if(IsSame(L"Gray", type)) { if(value2.Length()) { int delta = TTypeConvert::Str2Int(value2); resultMat = CvHelper::BuildTransMaskMat(srcMat, BYTE(v1), delta); } else resultMat = CvHelper::BuildTransMaskMat(srcMat, BYTE(v1)); } lua->AddReturnValue(resultMat, NextTwoParam(params, paramIndex), L"屏蔽图"); } else if(IsSame(L"drMAT_GetIcon", funName)) { cv::Mat maskMat = lua->ParseMat(THelper::GetLuaParamAt(params, paramIndex++)); UnicodeString iconSizeString = THelper::GetLuaParamAt(params, paramIndex++); int iconWidth = THelper::String::GetRegMatchAt_Int(iconSizeString, L"-?\\d+", 0); int iconHeight = THelper::String::GetRegMatchAt_Int(iconSizeString, L"-?\\d+", 1); int index = THelper::GetLuaParamAt(params, paramIndex++, L"0").Trim().ToInt(); CvRects rects = GetIconRects(maskMat, iconWidth, iconHeight); if(index < 0) index += rects.size(); if(IS_IN_RANGE(index, 0, rects.size() - 1)) { cv::Rect r = rects[index]; resultMat = CvHelper::CopySubMat(srcMat, r); } lua->AddReturnValue(resultMat, NextTwoParam(params, paramIndex), L"目标图标"); } else if(IsSame(L"drMAT_GetFeature", funName)) { UnicodeString featureName = THelper::GetLuaParamAt(params, paramIndex++); if(IsSame(L"countNonZero", featureName)) { cv::Mat tempMat = CvHelper::ToMat_GRAY(srcMat); threshold(tempMat, tempMat, 0x7F, 0xFF, cv::THRESH_BINARY); lua->AddReturnValue(int(countNonZero(tempMat))); } else if(IsSame(L"whiteWeight", featureName)) { // 白色比重 cv::Mat tempMat = CvHelper::ToMat_GRAY(srcMat); threshold(tempMat, tempMat, 0x7F, 0xFF, cv::THRESH_BINARY); double result = int(countNonZero(tempMat)) * 100.0 / tempMat.total(); lua->AddReturnValue(result); } } else if(IsSame(L"drMAT_countNonZero", funName)) { cv::Mat tempMat = CvHelper::ToMat_GRAY(srcMat); threshold(tempMat, tempMat, 0x7F, 0xFF, cv::THRESH_BINARY); int count = countNonZero(tempMat); lua->AddReturnValue(count); } else if(IsSame(L"drMAT_resize", funName)) { TPoint size = lua->ParsePoint(THelper::GetLuaParamAt(params, paramIndex++)); resize(srcMat, resultMat, cv::Size(size.x, size.y)); lua->AddReturnValue(resultMat, NextTwoParam(params, paramIndex), L"缩放图"); } else return false; } else return false; return true; }
实例调用
简单测试一个背景处理功能
测试用图
测试用LUA代码
function test() Initial() realTimeMat = win:GetRealtimeMat(realTimeMat) tempMat = cv:Convert(realTimeMat, "Background=0xFF, 0x0") -- 白色背景,黑色前景 tempMat = cv:Convert(realTimeMat, "Background=0x0, 0xFF") -- 黑色背景,白色前景 tempMat = cv:Convert(realTimeMat, "Background=0xFF") -- 白色背景,前景不变 tempMat = cv:Convert(realTimeMat, "Background=0x0") -- 黑色背景,前景不变 return LUA_STATUS_OK end
运行结果
总结
方法可行,基于此可实现各种脚本自动化。先把已有功能写成文档,便于后续开发使用。
相关文章推荐
- 最近在开发高智能android脚本(基于高精度图像识别,拥有机器学习框架,验证码识别,图像相似度对比等等的),有用到adb,可能以后要来开发脚本,几个笔记
- 使用CloudSight API进行图像识别的Python脚本
- 使用CloudSight API进行图像识别的Python脚本
- 通过lua脚本识别微信,支付宝,龙支付
- Lua脚本在C++下的舞步(三)
- PDF 文件中可识别图像的提取
- [转]Java OCR 图像智能字符识别技术,可识别中文
- 【转贴】如何在C++中集成Lua脚本(LuaPlus篇)
- 【COCOS2DX-LUA 脚本开发之十一】C/C++与Lua之间进行数据函数交互以及解决“PANIC: unprotected error in call to Lua API (attempt t
- 图像识别技术突破成功,发文庆贺!
- cocos2d-x的lua脚本如何加载Cocostudio制作的UI文件
- 【COCOS2DX-LUA 脚本开发之十三】解决lua项目编译Android出现get data from file failed以及路径等问题
- CSDN验证码识别技术,图像识别技术
- 长年承接AR图像识别项目,关于高速UnityARCam多图问题技术整理
- 图像识别和机器学习
- lua脚本之lua语言简介以及lua的安装
- 图像处理和图像识别中常用的329个OpenCV函数
- 【COCOS2DX-LUA 脚本开发之十四】解决自定义CPP类通过TOLUA++ BINDING LUACOCOS2D后编译到ANDROID运行黑屏(没有调用自定义CPP类)的问题!
- Lua脚本调用C函数小结
- 图像识别——象棋识别相关论文资料算法暂存