这个春节一直猫在家,不给政府添乱。今天是元宵节,正想出去一趟,微信群看到一条信息,立马就不动了:今天千万不要外出,不然会被病毒笑话的:原来你们躲得过初一,躲不过十五。 那就先把这个十五躲过去,继续宅。
废话少说,其实我用LUA也就是点皮毛。就用这点皮毛扎个小辫,给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
直接调用实例对象的方法函数即可。
如要取得某Mat子图,直接调用mat = cv:SubMat(mat, “86, 712, 1120, 4”)
主要是响应相应的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;
}
简单测试一个背景处理功能
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