python-opencv-Rng隨機數問題(解決方案python-cpp擴充套件復現)
阿新 • • 發佈:2020-12-09
技術標籤:Python
我嘗試用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.pysetup.pycvRNG.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);
}