C ++中的OpenCV Integer除法与预期不符

时间:2014-09-22 06:44:35

标签: c++ opencv

给出以下输出:

[11233,11334,11434,10897] [44,44,45,43] [-31,81,-86,-111]

来自此代码

std::cout << mat32sc1;
channels[1] = mat32sc1 / 256;
channels[0] = mat32sc1 - channels[1] * 256;
std::cout << channels[1];
std::cout << channels[0];

我原以为11233/256是43,使用整数除法?

我的假设是否冤枉c ++总是通过地板进行整数划分?

更新

这是我目前的编码功能。

void encode(cv::Mat & src, cv::Mat & dst)
{
    cv::Mat_<int> mat32sc1;
    src.convertTo(mat32sc1, CV_32SC1, 10, 11000);

    std::vector<cv::Mat> channels;
    channels.resize(3);

//  bitwise_and(mat32sc1, cv::Scalar(255), channels[0]); // is this needed or will converTo truncate automaticly.
//  channels[0].convertTo(channels[0], CV_8UC1);
//  mat32sc1.convertTo(channels[1], CV_8UC1, 1.0 / (1 << 8));
    channels[2] = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
    int flag = 256;
//  std::cout << mat32sc1;
    channels[1] = mat32sc1 / flag;
    channels[0] = mat32sc1 - channels[1] * flag;
    cv::Mat_<int> off = (channels[0] < 0) / 255;
    //std::cout << off;
    channels[1] -= off;
    channels[0] = mat32sc1 - channels[1] * flag;


    //std::cout << channels[1];
    //std::cout << channels[0];
    channels[0].convertTo(channels[0], CV_8UC1);
    channels[1].convertTo(channels[1], CV_8UC1);

    cv::merge(channels, dst);
}

任何更聪明的方法来获得相同的结果

3 个答案:

答案 0 :(得分:3)

该分裂确实不是整数分裂。 OpenCV中的大多数函数将其输入转换为Scalar,Scalar是1,2,3或4个双精度的容器。 OpenCV中执行类似操作的其他函数(scaleAdd,addWeighted,convertTo等等)也都可以使用双精度函数。换句话说,您的代码通过对结果进行双重舍入来进行除法。这就是你得到44而不是43的原因。

修改

至于&#34;编码&#34;你不需要执行复杂的操作。新矩阵的字节已经存在。您只需要创建方便的访问方式:

Mat temp(src.size(), CV_8UC4, src.data);

这将创建指向src数据的新矩阵标题(即没有数据副本)。但不是将数据看作单通道的整数矩阵,而是4通道矩阵的无符号字符(具有相同的宽度和高度)。你可以用多通道矩阵做任何事情:split(),merge(),mixChannels()等......

答案 1 :(得分:2)

不,你是对的,整数除法是用C ++中的地板进行的。请参阅 [expr.mul]

  

对于积分操作数,/运算符产生代数商,丢弃任何小数部分; 81

     

81)这通常被称为零截断。

答案 2 :(得分:0)

这是一个手工制作的功能,可以根据您的想法对OpenCV执行整数除法。 希望它有所帮助。

#include "opencv2\highgui.hpp"
using cv::Mat;
#include "opencv2\imgproc.hpp"
using cv::threshold;
void IntegerDivide(Mat& Input_Dividendo, int Input_Divisor, Mat& Output_Cociente, Mat& Output_Resto)
{
    // Input_Dividendo is supposed to be CV_32S
    // Input_Dividendo = Input_Divisor * Output_Cociente + Output_Resto

    Mat candidato_Cociente=Input_Dividendo/Input_Divisor;
    Mat offset=Input_Dividendo-(candidato_Cociente*Input_Divisor);
    Mat error_en_candidato_Cociente;

    // Threshold
    // threshold( offset, error_en_candidato_Cociente, 0, 1,CV_THRESH_BINARY_INV);
    Mat aux_src;
    offset.convertTo(aux_src,CV_32F);
    Mat aux_dst;
    threshold( aux_src, aux_dst, 0, 1,CV_THRESH_BINARY_INV);
    aux_dst.convertTo(error_en_candidato_Cociente,CV_32S);  
    // End threshold

    Output_Cociente=candidato_Cociente-error_en_candidato_Cociente;

    Output_Resto=Input_Dividendo-(Output_Cociente*Input_Divisor);
}