*以下内容并非正规解决方案,效仿请谨慎。
之前有介绍过阿里云的鉴黄API接口http://blog.csdn.net/sm9sun/article/details/53321888
其支持:porn: 黄图检测,ocr:文字识别,illegal: 暴恐敏感识别三个业务
其API也很人性的把其返回的json串做出了解析,我们可以直接拿到相应的返回值。
而如果想对其做进一步的开发,比如说拿到ocr后再做敏感词识别
字典树实现敏感词检索http://blog.csdn.net/sm9sun/article/details/53308643
那么想了想最好还是回到C++去处理这部分工作。
之前也有写过C++嵌入python开发的博客http://blog.csdn.net/sm9sun/article/details/53392760
网上找了一下,也确实有实现python的字典与C++ map容器转换的方法(用PyDict_Next遍历python的字典对象)
不过想来想去总是感觉有一些麻烦。反正字符串是万能的,我们还不如干脆拿到python的返回json串(实际是转换后的string字符串)
然后自己去做解析处理,简单粗暴~
首先我们需要strstr函数来进行字典关键词的匹配,但是有一个问题,我们知道strstr匹配不到的时候会返回NULL指针的,而我们把json串当作string去匹配处理的话肯定会出现某个字典匹配不到的情况,那么这就非常的不安全。所以我们在其外部套了一层,也顺便把字典名给去掉
string my_strstrEX(char * _Str,const char * _SubStr)
{
char *posStr=strstr(_Str,_SubStr);
if(posStr==NULL)
{
return "";
}
else
{
return string(posStr+strlen(_SubStr));
}
}
/*
功能:去掉区间符号
dictword:字典字符串
c :区间符,例如:[] '' "" (){}
return :关键词
*/
string getKeyBydictword(string dictword,char c)
{
if(strlen(dictword.c_str())<2) //如果长度小于2,直接返回错误
{
return "ErrorString";
}
char ec=c; //结束符
if('\"'==c) ec='\"';
if('\''==c) ec='\'';
if('['==c) ec=']';
if('('==c) ec=')';
if('{'==c) ec='}';
int si=0,ei=-1;
int nsi=0,nei=0;//记录符号出现的次数,当nsi和nei相等时,说明其是匹配的一对
for(int i=0;i<=strlen(dictword.c_str())-1;i++)
{
if(dictword[i]==ec&&(nsi>nei)) //因为某些区间符两边相等,如"",所以判断标准为nsi>nei
{
nei++;
if(nsi==nei)
{
ei=i;
break;
}
}
else if(dictword[i]==c)
{
nsi++;
if(nsi==1)
{
si=i+1;
}
}
}
if(nei>0)
return dictword.substr(si,ei-si);
else
return "ErrorString";
}
接下来就是主函数的调用了
完整代码:
// call_py_test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Python.h"
#include
#include
using namespace std;
/*
图像识别py
返回字典结构体
*/
struct retdict
{
string strCode; //执行信息
string strMsg; //异常信息
string strOcr; //文字识别
int nPorn; //色情返回值
int nIllegal; //暴恐返回值
};
/*
由于strstr匹配不到检索字串Substr时会返回NULL
考虑到安全性问题,故在此加了一层NULL的处理
额外过滤掉检索字串的长度
*/
string my_strstrEX(char * _Str,const char * _SubStr)
{
char *posStr=strstr(_Str,_SubStr);
if(posStr==NULL)
{
return "";
}
else
{
return string(posStr+strlen(_SubStr));
}
}
/*
const char*的重载
*/
string my_strstrEX(const char * _Str,const char * _SubStr)
{
const char *posStr=strstr(_Str,_SubStr);
if(posStr==NULL)
{
return "";
}
else
{
return string(posStr+strlen(_SubStr));
}
}
/*
功能:去掉区间符号
dictword:字典字符串
c :区间符,例如:[] '' "" (){}
return :关键词
*/
string getKeyBydictword(string dictword,char c)
{
if(strlen(dictword.c_str())<2) //如果长度小于2,直接返回错误
{
return "ErrorString";
}
char ec=c; //结束符
if('\"'==c) ec='\"';
if('\''==c) ec='\'';
if('['==c) ec=']';
if('('==c) ec=')';
if('{'==c) ec='}';
int si=0,ei=-1;
int nsi=0,nei=0;//记录符号出现的次数,当nsi和nei相等时,说明其是匹配的一对
for(int i=0;i<=strlen(dictword.c_str())-1;i++)
{
if(dictword[i]==ec&&(nsi>nei)) //因为某些区间符两边相等,如"",所以判断标准为nsi>nei
{
nei++;
if(nsi==nei)
{
ei=i;
break;
}
}
else if(dictword[i]==c)
{
nsi++;
if(nsi==1)
{
si=i+1;
}
}
}
if(nei>0)
return dictword.substr(si,ei-si);
else
return "ErrorString";
}
int main(int argc, char** argv)
{
//初始化Python
//在使用Python系统前,必须使用Py_Initialize对其
//进行初始化。它会载入Python的内建模块并添加系统路
//径到模块搜索路径中。这个函数没有返回值,检查系统
//是否初始化成功需要使用Py_IsInitialized。
Py_Initialize();
// 检查初始化是否成功
if ( !Py_IsInitialized() )
{
return -1;
}
// 添加当前路径
//把输入的字符串作为Python代码直接运行,返回0
//表示成功,-1表示有错。大多时候错误都是因为字符串
//中有语法错误。
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyObject *pName,*pModule,*pDict,*pFunc,*pArgs;
// 载入脚本
pName = PyString_FromString("imgfocpp");
pModule = PyImport_Import(pName);
if ( !pModule )
{
printf("can't find imgfocpp.py");
getchar();
return -1;
}
pDict = PyModule_GetDict(pModule);
if ( !pDict )
{
return -1;
}
// 找出函数名为retStr_test的函数
pFunc = PyDict_GetItemString(pDict, "imgmain");
if ( !pFunc || !PyCallable_Check(pFunc) )
{
printf("can't find function [imgmain]");
getchar();
return -1;
}
// 参数进栈
*pArgs;
pArgs = PyTuple_New(1);
// PyObject* Py_BuildValue(char *format, ...)
// 把C++的变量转换成一个Python对象。当需要从
// C++传递变量到Python时,就会使用这个函数。此函数
// 有点类似C的printf,但格式不同。常用的格式有
// s 表示字符串,
// i 表示整型变量,
// f 表示浮点数,
// O 表示一个Python对象。
string arg1="图片的URL";
PyTuple_SetItem(pArgs, 0, Py_BuildValue("s",arg1.c_str()));
// 调用Python函数
char* strRet;
PyObject* result=PyObject_CallObject(pFunc, pArgs);
//返回值类型转换
PyArg_Parse(result, "s", &strRet);
//cout<<"strRet="<
C++做字符串解析工作,python代码就很简单了,直接返回string类型的json串就好。
#coding=utf-8
def imgmain(imgurl):
import sys
reload(sys)
sys.setdefaultencoding('gbk')
imgurl2=imgurl.encode('utf8')
sys.setdefaultencoding('utf8')
# 同步图片检测服务接口, 会实时返回检测的结果
from aliyunsdkcore import client
from aliyunsdkgreen.request.v20161018 import ImageDetectionRequest
import json
# 请替换成你自己的accessKeyId、accessKeySecret, 您可以类似的配置在配置文件里面,也可以直接明文替换
#clt = client.AcsClient("1", "2",'3')
clt = client.AcsClient("你自己的accessKeyId", "你自己的accessKeySecret",'cn-hangzhou')
request = ImageDetectionRequest.ImageDetectionRequest()
request.set_accept_format('json')
# 设置成同步调用
request.set_Async('false')
# 设置要检测的图片链接
# json字符串格式, 同步只支持单张图片
request.set_ImageUrl(json.dumps([imgurl2]))
# 设置要检测的服务场景
# 异步支持多个场景同时识别
# porn: 黄图检测
# ocr: ocr文字识别
# illegal: 暴恐敏感识别
request.set_Scene(json.dumps(["porn","ocr","illegal"]))
response = clt.do_action(request)
#"The request has failed due to a temporary failure of the server"
print response.encode('gbk')
return response.encode('gbk')
调用成功截图:
注:ocr返回的其实是个列表,所以用引号括起来,每个独立的词汇后面会有一个“,”这里就先不作处理,
等与敏感词检索联立时再进行切分。
调用失败截图: