OpenCV中的图像复制机制

在这里,首先对Fred_Yang2013表示衷心的感谢,是他的博客给了我很大的提示,还有坛友xjtuzhw的无私帮助亦表示感谢。

本人opencv入门,写了一个给图像文件加噪声的子函数salt.cpp,然后再主函数main中调用,用以显示原图像文件和加噪声文件之间的明显对比。但是现在出现了一个问题,如果我先调用salt()函数,然后imshow()显示原图和加噪之后的图片,会发现显示的两幅图片均是加噪后的结果,原图片被修改了。但是我若是先imshow原图片,然后加噪声salt(),此时再用imshow()加噪的图片,才是我想要的结果。其实这对程序本身没什么影响,但是我想知道怎样才能达到如下目的:先调用salt(),然后imshow()原图片和加噪图片,使得原始图像和加噪图像均能正常地显示?(原始图像和加噪图像能正常的对比显示?)

语言叙述不是很清晰:具体代码请大家过目

先是加噪的子函数salt(),独立存储为salt.cpp

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;
 void salt(cv::Mat &image,cv::Mat &resultimg,int n){
         resultimg=image;
         for(int k=0;k<n;k++){
                int i=rand()%resultimg.cols;
                int j=rand()%resultimg.rows;
                if(resultimg.channels()==1){//graylevel image
                                        resultimg.at<uchar>(j,i)=255;
                }else if(resultimg.channels()==3){//color image
                        resultimg.at<cv::Vec3b>(j,i)[0]=255;
                        resultimg.at<cv::Vec3b>(j,i)[1]=255;
                        resultimg.at<cv::Vec3b>(j,i)[2]=255;
                }
        }
        
}

然后是调用salt()的主函数,存储为ex1.cpp

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//隐藏控制台窗口
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
//调用salt.cpp中子函数的方法
void salt(cv::Mat &image,cv::Mat &resultimg,int n);

int main()
{
        const char *pstrImageName = "lena.jpg";
        const char *pstrSaveImageName = "lena_resize.jpg";
        const char *pstrWindowsSrcTitle = "原图 ";
        const char *pstrWindowsDstTitle = "缩放图";
        //初始化图像对象
        cv::Mat image=cv::imread(pstrImageName);
        cv::Mat resultimg ; 
        
    cv::namedWindow(pstrWindowsSrcTitle);
    cv::namedWindow(pstrWindowsDstTitle);
    
        

    salt(image,resultimg,3000);
        
        cv::imshow("original",image);
        cv::imshow("salt result",resultimg);
        
        cv::waitKey(0);
        return 1;
}

运行结果

是不是我的子函数设计出现了问题?本人cPP基础不好 还请这里的大神多多指教!

后来 经过自己的摸索 发现

原来opencv中的Mat类使用引用计数,当图像赋值给另一个变量时,不用复制,只是将之指向相同的内存块,引用计数加一。当所有对图像引用取消时,内存才被释放,且只释放一次。因而普通的赋值操作“=”实质上是共享同一块内存空间,此时产生的操作会对所有的"="关联的变量起作用。如果要实现真正的独享操作,opencv提供了copyto()来实现。因而salt()代码更改如下:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
 void salt(cv::Mat &image,cv::Mat &resultimg,int n){
         image.copyto(resultimg);
         for(int k=0;k<n;k++){
                int i=rand()%resultimg.cols;
                int j=rand()%resultimg.rows;
                if(resultimg.channels()==1){//graylevel image
                                        resultimg.at<uchar>(j,i)=255;
                }else if(resultimg.channels()==3){//color image
                        resultimg.at<cv::Vec3b>(j,i)[0]=255;
                        resultimg.at<cv::Vec3b>(j,i)[1]=255;
                        resultimg.at<cv::Vec3b>(j,i)[2]=255;
                }
        }
         
}
此时结果为理想状态



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值