首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在CV::Mat中没有更新图像像素值(OpenCV 4.1.2;C++)

在CV::Mat中没有更新图像像素值(OpenCV 4.1.2;C++)
EN

Stack Overflow用户
提问于 2019-12-12 18:51:35
回答 1查看 216关注 0票数 0

我正在尝试实现抖动算法 (使用OpenCV 4.1.2在Qt上使用MSVC 2015 c++编译器)。

当我试图更新cv::Mat对象值时,我遇到了一个问题,但我无法这样做。虽然我找到了一种解决这个问题的方法,但我仍然不明白为什么函数Mat img中的dithering 行: 90不会改变,但是如果使用注释的行: 105而不是行: 104,代码就会工作。

我的问题是:为什么会发生这种事?是因为cv::Mat 以某种方式传递了指针或减少的彩色图像的地址吗?或者只是一些OpenCV的魔力?

图片和结果:原始图像 约简图像 结果图像(无错误) 结果图像(有错误)

代码语言:javascript
复制
    1. #include <vector>
    2. #include <sstream>
    3. #include <iostream>
    4. 
    5. #include <opencv2/core.hpp>
    6. #include <opencv2/opencv.hpp>
    7. #include <opencv2/highgui.hpp>
    8. #include <opencv2/imgcodecs.hpp>
    9. #include <opencv2/core/matx.hpp>
    10.#include <opencv2/core/utility.hpp>
    11. 
    12. 
    13. using namespace std;
    14. using namespace cv;
    15. 
    16. 
    17. Mat init(int argc, char *argv[]);
    18. Mat reduceVal(Mat src);
    19. uchar reduceVal(uchar);
    20. Mat dithering(Mat src);
    21. uchar addError(uchar pixel, int error, float numerator, float denominator);
    22. 
    23. 
    24. int main(int argc, char *argv[])
    25. {
    26.     Mat image = init(argc, argv);
    27.     if (image.empty()) {
    28.         cout << "Wrong argumnets or no image data\n";
    29.         return -1;
    30.     }
    31. 
    32.     namedWindow("Colored Image", WINDOW_AUTOSIZE);
    33.     imshow("Colored Image", image);
    34. 
    35.     Mat reducedImage(image.rows, image.cols, image.type());
    36.     reducedImage = reduceVal(image.clone());
    37.     namedWindow("Reduced Value Image", WINDOW_AUTOSIZE);
    38.     imshow("Reduced Value Image", reducedImage);
    39. 
    40.     Mat ditheredImage(image.rows, image.cols, image.type());
    41.     ditheredImage = dithering(image.clone());
    42.     namedWindow("Dithert Image", WINDOW_AUTOSIZE);
    43.     imshow("Dithert Image", ditheredImage);
    44. 
    45.     imwrite("reducedImage.png", reducedImage);
    46.     imwrite("floyedSteinberg_image.png", ditheredImage);
    47.     waitKey(0);
    48.     return 0;
    49. }
    50. 
    51. Mat init(int argc, char *argv[])
    52. {
    53.     if (argc < 2) {
    54.         cout << "Huston we have a problem" << endl;
    55.         return Mat();
    56.     }
    57.     string imageName = argv[1];
    58.     Mat image = imread(imageName, IMREAD_COLOR);
    59.     return image;
    60. }
    61. 
    62. Mat reduceVal(Mat img)
    63. {
    64.     int rows = img.rows;
    65.     img = img.reshape(0, 1);
    66.     for (int i = 0; i < img.cols; i++) {
    67.         for (int k = 0; k < 3; k++) {
    68.             uchar colorVal = img.at<Vec3b>(i)[k];
    69.             if (colorVal < (255 - 51)) {
    70.                 colorVal = uchar(colorVal / 51 + 0.5) * 51;
    71.             } else {
    72.                 colorVal = 255;
    73.             }
    74.             img.at<Vec3b>(i)[k] = colorVal;
    75.         }
    76.     }
    77.     return img.reshape(0, rows).clone();
    78. }
    79. 
    80. uchar reduceVal(uchar colorVal)
    81. {
    82.     if (colorVal < (255 - 51)) {
    83.         return uchar(colorVal / 51 + 0.5) * 51;
    84.     } else {
    85.         return 255;
    86.     }
    87. }
    88. 
    89. 
    90. Mat dithering(Mat img)
    91. {
    92.     uchar oldPixel, newPixel;
    93.     int quantError;
    94.     Mat imageNew(img.rows, img.cols, img.type());
    95.     imageNew = reduceVal(img.clone());
    96.     imshow("dithering begin ", img);
    97.     imshow("Reduced Image", imageNew);
    98.     for (int r = 0; r < img.rows - 1; r++) {
    99.         for (int c = 1; c < img.cols - 1; c++) {
    100.            Point anchor(c, r);
    101.            for (int k = 0; k < img.channels(); k++) {
    102.                Point pt = anchor;
    103.                oldPixel = img.at<Vec3b>(pt)[k];
    104.                newPixel = imageNew.at<Vec3b>(pt)[k];
    105. //             newPixel = reduceVal(oldPixel);
    106.                img.at<Vec3b>(pt)[k] = newPixel;
    107.                quantError = oldPixel - newPixel;
    108.                pt = Point(anchor.x + 1, anchor.y);
    109.        img.at<Vec3b>(pt)[k] = addError(img.at<Vec3b>(pt)[k], quantError, 7.0f, 16.0f);
    110.                pt = Point(anchor.x - 1, anchor.y + 1);
    111.        img.at<Vec3b>(pt)[k] = addError(img.at<Vec3b>(pt)[k], quantError, 3.0f, 16.0f);
    112.                pt = Point(anchor.x, anchor.y + 1);
    113.        img.at<Vec3b>(pt)[k] = addError(img.at<Vec3b>(pt)[k], quantError, 5.0f, 16.0f);
    114.                pt = Point(anchor.x + 1, anchor.y + 1);
    115.        img.at<Vec3b>(pt)[k] = addError(img.at<Vec3b>(pt)[k], quantError, 1.0f, 16.0f);
    116.            }
    117.        }
    118.    }
    119.    return img;
    120. }
    121. 
    122. uchar addError(uchar pixel, int error, float numerator, float denominator)
    123. {
    124.    int sum = pixel + static_cast<int>(error * (numerator / denominator));
    125.    if (sum > 255) {// making sure that 'sum' belongs to [0,255]
    126.        return uchar(255);
    127.    } else if (sum < 0) {
    128.        return 0;
    129.    } else {
    130.        return uchar(sum);
    131.    }
    132. }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-12 19:49:24

您的代码在循环的每一次迭代中都修改img的数据。我的意思是,当您处理(x,y)时,像素(x+1,y)(x-1,y+1)(x,y+1)(x+1,y+1)会被更改并存储在img中。因此,在下一次迭代中,您使用前面步骤中的修改值计算新值(这是使用newPixel = reduceVal(oldPixel);)的情况)。

代码语言:javascript
复制
  -------->          
  |
  |      C x   you iterate from top to bottom, from left to right 
  |    x x x   so error value is propagated with next iterations 
 \ /

上述情况在案件中不会发生

代码语言:javascript
复制
newPixel = imageNew.at<Vec3b>(pt)[k];

因为您读取的像素值是在不使用addError调用的情况下计算的--这些值不受邻居值的影响。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59311078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档