Использование скобок для расчета в C - PullRequest
1 голос
/ 18 апреля 2020

У меня есть назначение дизеринга с использованием OpenCV. Я понимаю этот метод и кодировал его в C ++, но я нашел то, что не могу понять в скобках.

Когда я выполняю этот код:

#include<opencv2/opencv.hpp>
#include<highgui.hpp>
#include<iostream>
#include<opencv2/cvconfig.h>
using namespace cv;
using namespace std;

int main() {
    Mat img = imread("lena.jpg", IMREAD_COLOR);
    Mat bgr[3];
    Mat dithering[3];
    int x = img.rows;
    int y = img.cols;
    Mat merger;
    Mat temp(x, y, CV_64FC1, Scalar(0));
    double e;

    split(img, bgr);

    for (int l = 0; l < 3; l++) {
        bgr[l].convertTo(temp, CV_64FC1);
        for (int i = 0; i < x - 1; i++) {
            for (int j = 1; j < y - 1; j++) {
                if (temp.at<double>(i, j) > 127)
                    e = temp.at<double>(i, j) - 255;
                else
                    e = temp.at<double>(i, j);

                temp.at<double>(i, j + 1) = temp.at<double>(i, j + 1) + e * (7 / 16);
                temp.at<double>(i + 1, j - 1) = temp.at<double>(i + 1, j - 1) + e * (3 / 16);
                temp.at<double>(i + 1, j) = temp.at<double>(i + 1, j) + e * (5 / 16);
                temp.at<double>(i + 1, j + 1) = temp.at<double>(i + 1, j + 1) + e * (1 / 16);
            }
        }
        dithering[l] = Mat(x, y, CV_8UC1, Scalar(0));

        for (int i = 0; i < x; i++) {
            for (int j = 0; j < y; j++) {
                if (temp.at<double>(i, j) > 127)
                    dithering[l].at<uchar>(i, j) = 255;
                else
                    dithering[l].at<uchar>(i, j) = 0;
            }
        }
    }
    merge(dithering,3, merger);

    imwrite("dithered.jpg", merger);
    namedWindow("original", WINDOW_AUTOSIZE);
    namedWindow("dithered", WINDOW_AUTOSIZE);

    imshow("original", img);
    imshow("dithered", merger);

    waitKey(0);
}

У меня есть эти результаты

image

Это очень плохие результаты.

Но когда я удаляю скобки в расчете:

temp.at<double>(i, j + 1) = temp.at<double>(i, j + 1) + e * 7 / 16;
temp.at<double>(i + 1, j - 1) = temp.at<double>(i + 1, j - 1) + e * 3 / 16;
temp.at<double>(i + 1, j) = temp.at<double>(i + 1, j) + e * 5 / 16;
temp.at<double>(i + 1, j + 1) = temp.at<double>(i + 1, j + 1) + e * 1 / 16;

Я получил правильные результаты:

image

Я не смог найти разницу между ними, но они дают разные результаты.

Может кто-нибудь объяснить это для меня?

1 Ответ

3 голосов
/ 18 апреля 2020

В этом выражении

e * (7 / 16)

подвыражение в скобках оценивается с помощью целочисленного арифметического c. То есть результат 7 / 16 равен 0. Таким образом, полное выражение также равно 0.

Без скобок выражение

e * 7 / 16

оценивается как

( e * 7 ) / 16

и здесь используется арифметика c с числами с плавающей запятой (переменная e объявлена ​​как имеющая тип double), поскольку объекты типа int неявно преобразуются в тип double из-за обычных арифметических c преобразований для определения общего типа выражения.

...