我尝试用python复现,发现python没有uint,网上的ctypes也试了
import cv2
import numpy as np
from enum import Enum
from ctypes import c_uint64, c_uint32, c_ulong, c_uint
class RNG(object):
#https://www.jb51.cc/python/533198.html
#考虑到C溢出,如何在Python中使用64位无符号整数数学?
#8个f实际上是十六进制,一个十六进制数对应4位二进制,所以8个就表示32位
#18446744073709551615(uint64的最大值)
def __init__(self, _state=None):
self.Type = Enum("RandomType", (["UNIFORM", "NORMAL"]))
if _state == None:
self.state = 0xffffffff
else:
self.state = _state if _state else 0xffffffff
self.CV_RNG_COEFF = 4164903690
def uniform_int(self, a, b):
a = int(a)
b = int(b)
c = self.next()%(b-a)+a
return a if a == b else c
def next(self):
t1 = self.state * (self.CV_RNG_COEFF)
t2 = self.state >> 32
self.state = t1 + t2
return self.state
rng = RNG(0x34985739)
patchSize = 31
for i in range(512):
x = rng.uniform_int(-patchSize/2, patchSize/2+1)
y = rng.uniform_int(-patchSize/2, patchSize/2+1)
print("x,y: ", x, y)
debug = 1
没办法,最后就用python-cpp扩展
首先测试下:
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <complex>
#include <map>
#include <new>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
typedef int64_t int64;
typedef uint64_t uint64;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef signed char schar;
#define CV_RNG_COEFF 4164903690U
/*!
Random Number Generator
The class implements RNG using Multiply-with-Carry algorithm
*/
class RNG
{
public:
enum { UNIFORM=0, NORMAL=1 };
RNG();
RNG(uint64 state);
//! updates the state and returns the next 32-bit unsigned integer random number
unsigned next();
operator uchar();
operator schar();
operator ushort();
operator short();
operator unsigned();
//! returns a random integer sampled uniformly from [0, N).
unsigned operator ()(unsigned N);
unsigned operator ()();
operator int();
operator float();
operator double();
//! returns uniformly distributed integer random number from [a,b) range
int uniform(int a, int b);
//! returns uniformly distributed floating-point random number from [a,b) range
float uniform(float a, float b);
//! returns uniformly distributed double-precision floating-point random number from [a,b) range
double uniform(double a, double b);
//! returns Gaussian random variate with mean zero.
double gaussian(double sigma);
uint64 state;
};
// Multiply-with-Carry RNG
inline RNG::RNG() { state = 0xffffffff; }
inline RNG::RNG(uint64 _state) { state = _state ? _state : 0xffffffff; }
inline unsigned RNG::next()
{
state = (uint64)(unsigned)state*CV_RNG_COEFF + (unsigned)(state >> 32);
return (unsigned)state;
}
inline RNG::operator uchar() { return (uchar)next(); }
inline RNG::operator schar() { return (schar)next(); }
inline RNG::operator ushort() { return (ushort)next(); }
inline RNG::operator short() { return (short)next(); }
inline RNG::operator unsigned() { return next(); }
inline unsigned RNG::operator ()(unsigned N) {return (unsigned)uniform(0,N);}
inline unsigned RNG::operator ()() {return next();}
inline RNG::operator int() { return (int)next(); }
// * (2^32-1)^-1
inline RNG::operator float() { return next()*2.3283064365386962890625e-10f; }
inline RNG::operator double()
{
unsigned t = next();
return (((uint64)t << 32) | next())*5.4210108624275221700372640043497e-20;
}
inline int RNG::uniform(int a, int b) {
return a == b ? a : (int)(next()%(b - a) + a);
}
inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; }
inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; }
int main() {
int patchSize = 31;
RNG rng(0x34985739); // we always start with a fixed seed,
// to make patterns the same on each run
for( int i = 0; i < 512; i++ )
{
int x = rng.uniform(-patchSize/2, patchSize/2+1);
int y = rng.uniform(-patchSize/2, patchSize/2+1);
std::cout << x << " " << y << std::endl;
}
return 0;
}
然后写成扩展形式:
三个文件组成 main.py setup.py cvRNG.cpp
编译:
python setup.py install --record python_setup_log.txt
然后main.py文件调用
main.py
patchSize = 31
import cvRNG
list_x, list_y = cvRNG.orb_makeRandomPattern_uniform_int(512, int(-patchSize/2), int(patchSize/2+1))
setup.py
from distutils.core import *
from collections import defaultdict
import numpy #include <numpy/arrayobject.h>
# ext新建
ext_args = defaultdict(list)
# numpy
ext_args['include_dirs'].append(numpy.get_include())
ext_args['extra_compile_args'].append("-std=c++14")
#ext_args['extra_compile_args'].append("-stdlib=libc++")
module = [Extension("cvRNG", ["cvRNG.cpp", ], language="c++", **ext_args)]
setup(name='cvRNG', version="1.0", ext_modules=module)
#python setup.py install --record python_setup_log.txt
cvRNG.cpp
#include "Python.h"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <complex>
#include <map>
#include <new>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
using namespace std;
typedef int64_t int64;
typedef uint64_t uint64;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef signed char schar;
#define CV_RNG_COEFF 4164903690U
/*!
Random Number Generator
The class implements RNG using Multiply-with-Carry algorithm
*/
class RNG
{
public:
enum { UNIFORM=0, NORMAL=1 };
RNG();
RNG(uint64 state);
//! updates the state and returns the next 32-bit unsigned integer random number
unsigned next();
operator uchar();
operator schar();
operator ushort();
operator short();
operator unsigned();
//! returns a random integer sampled uniformly from [0, N).
unsigned operator ()(unsigned N);
unsigned operator ()();
operator int();
operator float();
operator double();
//! returns uniformly distributed integer random number from [a,b) range
int uniform(int a, int b);
//! returns uniformly distributed floating-point random number from [a,b) range
float uniform(float a, float b);
//! returns uniformly distributed double-precision floating-point random number from [a,b) range
double uniform(double a, double b);
//! returns Gaussian random variate with mean zero.
double gaussian(double sigma);
uint64 state;
};
// Multiply-with-Carry RNG
inline RNG::RNG() { state = 0xffffffff; }
inline RNG::RNG(uint64 _state) { state = _state ? _state : 0xffffffff; }
inline unsigned RNG::next()
{
state = (uint64)(unsigned)state*CV_RNG_COEFF + (unsigned)(state >> 32);
return (unsigned)state;
}
inline RNG::operator uchar() { return (uchar)next(); }
inline RNG::operator schar() { return (schar)next(); }
inline RNG::operator ushort() { return (ushort)next(); }
inline RNG::operator short() { return (short)next(); }
inline RNG::operator unsigned() { return next(); }
inline unsigned RNG::operator ()(unsigned N) {return (unsigned)uniform(0,N);}
inline unsigned RNG::operator ()() {return next();}
inline RNG::operator int() { return (int)next(); }
// * (2^32-1)^-1
inline RNG::operator float() { return next()*2.3283064365386962890625e-10f; }
inline RNG::operator double()
{
unsigned t = next();
return (((uint64)t << 32) | next())*5.4210108624275221700372640043497e-20;
}
inline int RNG::uniform(int a, int b) {
return a == b ? a : (int)(next()%(b - a) + a);
}
inline float RNG::uniform(float a, float b) { return ((float)*this)*(b - a) + a; }
inline double RNG::uniform(double a, double b) { return ((double)*this)*(b - a) + a; }
int main() {
int patchSize = 31;
RNG rng(0x34985739); // we always start with a fixed seed,
// to make patterns the same on each run
for( int i = 0; i < 512; i++ )
{
int x = rng.uniform(-patchSize/2, patchSize/2+1);
int y = rng.uniform(-patchSize/2, patchSize/2+1);
std::cout << x << " " << y << std::endl;
}
return 0;
}
///5 模块函数
static PyObject *orb_makeRandomPattern_uniform_int(PyObject *self, PyObject *args) {
//输入 nums, a, b
int nums = 0;
int a = 0;
int b = 0;
//失败会写入异常信息
if (!PyArg_ParseTuple(args, "iii", &nums,&a,&b))
{
printf("PyArg_ParseTuple");
return NULL; //会抛出异常
}
PyObject *list_x = PyList_New(0);
PyObject *list_y = PyList_New(0);
//申请空间 引用计数+1 不释放会内存泄漏
PyObject *items = NULL;
RNG rng(0x34985739);
// we always start with a fixed seed,
// to make patterns the same on each run
for( int i = 0; i < nums; i++ )
{
int x = rng.uniform(a, b);
int y = rng.uniform(a, b);
items = PyLong_FromLong(x);
PyList_Append(list_x, items);
Py_DECREF(items);//引用计数-1 为0清理
items = PyLong_FromLong(y);
PyList_Append(list_y, items);
Py_DECREF(items);//引用计数-1 为0清理
}
return Py_BuildValue("OO", list_x, list_y);
}
///4 模块函数列表
static PyMethodDef cvRNG_funcs[] = {
{
"orb_makeRandomPattern_uniform_int", //函数名称
orb_makeRandomPattern_uniform_int, //函数指针
METH_VARARGS,//参数标识 多参数
"orb_makeRandomPattern_uniform_int function." //函数说明 help(testmod)
},
{0,0,0,0}
};
///3 模块定义
static PyModuleDef cvRNG_module = {
PyModuleDef_HEAD_INIT,
"cvRNG", //模块名
"cvRNG", //模块说明 通过help(模块名)
-1, //模块空间,子解释器用,-1不使用
cvRNG_funcs //模块函数
};
///1 扩展库入口函数 PyInit_ 固定的开头 mymod模块名
PyMODINIT_FUNC PyInit_cvRNG(void)
{
///2 模块创建函数 参数 PyModuleDef
return PyModule_Create(&cvRNG_module);
}