python-opencv-Rng随机数问题(解决方案python-cpp扩展复现)

我尝试用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);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值