用递归方法实现图像的噪声

本文深入探讨了图像处理与AI音视频处理的关键技术,包括连通区域检测、灰度值阈值调节、连通区域白点个数阈值调整、以及通过算法优化实现高效图像处理和音视频特效生成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整个程序的流程是:

Main()

{

domain();    //寻找连通区域的总白点数

}

 

domain()

{

first()       //寻找连通区域的第一个白点数
{

round(){}    //寻找连通区域的其他白点数

}

}

 具体函数:

domain函数:声明两个数组num和flag。num用来存放对应像素点是黑点(0)或白点(1),flag用来标记对应像素点是否被访问过,未访问是false,访问过是true。考虑到检测连通区域时边缘可能会越界,因此将四周的flag设为true。

     first函数:用for循环寻找第一个白点,找到后将该白点的num值设为2(这是为后面判断连通区域白点个数作标记,如果连通区域白点个数小于阈值,就要把所有num为2的白点变成黑点)。然后调用round函数判断一片连通区域有多少个白点,如果多余阈值,就将num=2改为num=3(防止和下一个连通区域冲突),否则将所有num为2的白点变成黑点。

     round函数:将first函数找到的第一个白点的位置作为实参传过来。之后判断把连通区域的点是否为白点。同时对连通区域的白点又用递归调用round函数判断其连通区域,直到将一片连通区域的白点个数全部统计完。

 

代码中遇到的问题:

  1. clone函数已经包括将图片所有信息全部复制给另一个图片了,不用再单独将灰度值赋值了。如:

Mat img2=img1.clone();

//   img2.data[j*cols+i]=img1.data[j*cols+i]; 这一句不需要

  1. 尽量不使用全局变量,使用局部变量时,若其他函数不能用(变红),可以选择用传参的方式传给下一个函数。

  2. 对连通区域的第一个白点忘记标记为true,又忘记将第一个白点变黑。因此遇到了好多小白点没变黑的问题。

  3. 一个函数内不能定义另一个函数,但是可以调用。

  4. 结果效果不好可以调节灰度值的阈值和连通区域白点个数的阈值。

 

#include<opencv2/opencv.hpp>

#include<math.h>

using namespace cv;

using namespace std;

 

int rows,cols;

void domain(Mat img1) ;

void round(int xstart ,int ystart,int * num,bool * flag) ;

void first(int * num,bool * flag,Mat img2) ;

int number;

 

int main()

{

    Mat img= imread("1.jpg",CV_LOAD_IMAGE_GRAYSCALE );

    rows=img.rows;

    cols=img.cols;

   

    uchar *result;               //数组和地址的关系

    result=new uchar[rows*cols]; //动态分配一个数组result,存每个点的强度值,new分配的数组最后要用delete释放空间

 

    for(int j=0;j<(rows-1);j++)

    {

        for(int i=0;i<(cols-1);i++)

        {

        int x=img.data[j*cols+i]-img.data[(j+1)*cols+i+1];

        int y=img.data[(j+1)*cols+i]-img.data[j*cols+i+1];

        result[j*cols+i]=(uchar)sqrt(x*x+y*y);

 

        }

    }

    for(int j=0;j<(rows-1);j++)

    {

        for(int i=0;i<(cols-1);i++)

        {

            if(result[j*cols+i]<20)

            {

                img.data[j*cols+i] =0;

            }

            else

            {

                img.data[j*cols+i]=255;

            }

 

        }

        }

    delete [] result ;

   

   

    domain (img );

    namedWindow("image0", CV_WINDOW_AUTOSIZE);

    imshow("image0",img);

   

    waitKey();

    return 0;

}

   

void domain(Mat img1)   //找出一片区域的白点个数

{

    //int n;   //记录连通域白点个数

    Mat img2=img1.clone();

//  img2.data[j*cols+i]=img1.data[j*cols+i];

      int * num;  

    num=new int[rows*cols];

    bool * flag;

    flag=new bool[rows*cols];

 

    for(int j=0;j<rows;j++){

        for(int i=0;i<cols;i++){

            if(img2.data[j*cols+i]==255)

            {

                num[j*cols+i]=1;

                flag[j*cols+i]=false;

            }

            else

            {

                num[j*cols+i]=0;

                flag[j*cols+i]=false;

            }

        }

    }

    for(int i=0;i<cols;i++)       //四个边,第一行

        {

            flag[i]=true;

    }

    for(int i=0,j=rows-1;i<cols;i++)       //四个边,最后一行

        {

            flag[j*cols+i]=true;

    }

    for(int j=0;j<rows;j++)       //四个边,左边一列

        {

            flag[j]=true;

    }

    for(int i=cols-1,j=0;j<rows;j++)       //四个边,右边一列

        {

            flag[j*cols+i]=true;

    }

 

    first(num,flag,img2);

    namedWindow("image1", CV_WINDOW_AUTOSIZE);

    imshow("image1",img2);

    delete [] num ;

    delete [] flag ;

 

}

void first(int * num,bool * flag,Mat img2)   //寻找连通域的第一个白点

{

    for(int j=0;j<rows;j++){

        for(int i=0;i<cols;i++){

            if(num[j*cols+i]==1&&!flag[j*cols+i])

            {

                //round(i,j,num,flag);

                num[j*cols+i]=2;

                number=0;

                flag[j*cols+i]=true;

                round(i,j,num,flag);

                if(number<80)

                {

                  for(int a=0;a<rows;a++){

                  for(int b=0;b<cols;b++){

                  if(num[a*cols+b]==2)

                  {

                      img2.data[a*cols+b]=0;

                  }

                 

                  }

                  }

                }

                 else

                {

                    for(int a=0;a<rows;a++){

                  for(int b=0;b<cols;b++){

                  if(num[a*cols+b]==2)

                  {

                      num[a*cols+b]=3;

                  }

                 

                  }

                  }

                   

                }

            }

        }

    }

 

}

 

 

 

void round(int xstart ,int ystart,int * num,bool * flag)    //寻找连通域的白点数

{

   

    if(num[(ystart-1)*cols+xstart-1]==1&&!flag[(ystart-1)*cols+xstart-1])  //左上

    {

        number++;

        flag[(ystart-1)*cols+xstart-1]=true;

        num[(ystart-1)*cols+xstart-1]=2;

        round(xstart-1,ystart-1,num,flag);

    }

    if(num[(ystart-1)*cols+xstart]==1&&!flag[(ystart-1)*cols+xstart])  //

    {

        number++;

        flag[(ystart-1)*cols+xstart]=true;

        num[(ystart-1)*cols+xstart]=2;

        round(xstart,ystart-1,num,flag);

    }

    if(num[(ystart-1)*cols+xstart+1]==1&&!flag[(ystart-1)*cols+xstart+1])  //右上

    {

        number++;

        flag[(ystart-1)*cols+xstart+1]=true;

        num[(ystart-1)*cols+xstart+1]=2;

        round(xstart+1,ystart-1,num,flag);

    }

    if(num[ystart*cols+xstart-1]==1&&!flag[ystart*cols+xstart-1])  //

    {

        number++;

        flag[ystart*cols+xstart-1]=true;

        num[ystart*cols+xstart-1]=2;

        round(xstart-1,ystart,num,flag);

    }

    if(num[ystart*cols+xstart+1]==1&&!flag[ystart*cols+xstart+1])  //

    {

        number++;

        flag[ystart*cols+xstart+1]=true;

        num[ystart*cols+xstart+1]=2;

        round(xstart+1,ystart,num,flag);

    }

    if(num[(ystart+1)*cols+xstart-1]==1&&!flag[(ystart+1)*cols+xstart-1])  //左下

    {

        number++;

        flag[(ystart+1)*cols+xstart-1]=true;

        num[(ystart+1)*cols+xstart-1]=2;

        round(xstart-1,ystart+1,num,flag);

    }

    if(num[(ystart+1)*cols+xstart]==1&&!flag[(ystart+1)*cols+xstart])  //

    {

        number++;

        flag[(ystart+1)*cols+xstart]=true;

        num[(ystart+1)*cols+xstart]=2;

        round(xstart,ystart+1,num,flag);

    }

    if(num[(ystart+1)*cols+xstart+1]==1&&!flag[(ystart+1)*cols+xstart+1])  //右下

    {

        number++;

        flag[(ystart+1)*cols+xstart+1]=true;

        num[(ystart+1)*cols+xstart+1]=2;

        round(xstart+1,ystart+1,num,flag);

    }

   

}

 

转载于:https://my.oschina.net/zhangxuman/blog/338575

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值