关于图像处理的OpenCV的编程案例(二)

本文详细介绍了骰子状字块作画系统,通过大小设定、分类和赋值,以及原始图像特征值计算和映射,展示了如何将图像转化为骰子艺术。此外,涵盖了滤镜效果学习系统,包括颜色调整、艺术风格转换、光线处理和雕刻技术,如老照片、红绿互换、灰度、二值化等,并展示了实际的代码示例。
摘要由CSDN通过智能技术生成

第六章 骰子作画学习系统

6.1 骰子状字块

6.1.1 设定大小

可以根据需要,将骰子状子块大小设定为n×n个像素点的二值图像,骰子状字块内共有n×n个像素。

6.1.2 分类

可使用白色像素点个数进行分类,骰子状子块内,白色像素点的个数可能为0~n×n个,共计n×n+1种可能,即共有n×n+1种可能的骰子。

6.1.3 赋值

本系统中,骰子状子块的大小为3×3像素大小,因此其代表白色像素点的元素可能有0~9个,共计10种可能。为了处理上的方便,将具有N个值为1的像素点的骰子状子块称为N型骰子状子块。

6.2 原始图像特征值计算

将要进行骰子作画的原图像作为原始图像,将原始图像划分为n×n的互不相交的子块,计算每一个子块的和,然后将该和映射到[0,n×n]内,得到原始图像的特征值矩阵。

6.3 映射

在原始图像特征值和骰子状子块之间建立映射关系。具体的映射关系为:将原始图像特征值为N的子块与N型骰子状子块进行映射。例如,原始图像中特征值为8的子块与8型骰子状子块进行映射。

6.4 实验结果

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    int i,j;
    int X,Y;
    Y = src_img.cols;
    X = src_img.rows;
    //定义特征矩阵
    Mat Feature((X + 2) / 3, (Y + 2) / 3, CV_8UC(1), Scalar::all(0));
    //定义目标图像(骰子画)
    Mat dst_img(X, Y, CV_8UC(1), Scalar::all(0));
    Mat src_img2;
    cvtColor(src_img, src_img2, COLOR_BGR2GRAY);
    for (i = 0; i < X; i++)
        for (j = 0; j < Y; j++)
            Feature.at<uchar>(i / 3, j / 3) += src_img2.at<uchar>(i, j) / 9;
    for (i = 0; i < X / 3; i++)
        for (j = 0; j < Y / 3; j++)
            Feature.at<uchar>(i, j) /= ((255 / 9) * 9) / 9;
    //定义用来表示骰子的数组
    int T[10][3][3] = {
        //0个白点
        {0,0,0,
         0,0,0,
         0,0,0},
         //1个白点
        {0,0,0,
         0,1,0,
         0,0,0},
         //2个白点
        {1,0,0,
         0,0,0,
         0,0,1},
         //3个白点
        {1,0,0,
         0,1,0,
         0,0,1},
         //4个白点
        {1,0,1,
         0,0,0,
         1,0,1},
         //5个白点
        {1,0,1,
         0,1,0,
         1,0,1},
         //6个白点
        {1,1,1,
         0,0,0,
         1,1,1},
         //7个白点
        {1,0,1,
         1,1,1,
         1,0,1},
         //8个白点
        {1,1,1,
         1,0,1,
         1,1,1},
         //9个白点
        {1,1,1,
         1,1,1,
         1,1,1},
    };
    //映射
    for (i = 0; i < dst_img.rows; i++)
        for (j = 0; j < dst_img.cols; j++)
            dst_img.at<uchar>(i, j) = T[Feature.at<uchar>(i / 3, j / 3)][i % 3][j % 3];
    //阈值化处理
    threshold(dst_img, dst_img, 0.5, 255, THRESH_BINARY);
    imshow("骰子画", dst_img);
    waitKey();
    return 0;
}

在这里插入图片描述

第7章 滤镜效果学习系统

7.1颜色效果

7.1.1 老照片

将原始图像的RGB通道颜色进行处理以得到老照片的RGB通道,具体实现为:
在这里插入图片描述

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst_img(src_img.size(), CV_8UC3);
    for (int i = 1; i < src_img.rows - 1; i++)
    {
        uchar* p0 = src_img.ptr<uchar>(i);
        uchar* q0 = dst_img.ptr<uchar>(i);
        for (int j = 1; j < src_img.cols - 1; j++)
        {
            int srcR = p0[3 * j];
            int srcG = p0[3 * j + 1];
            int srcB = p0[3 * j + 2];
            int dstR, dstG, dstB;
            dstR = (101 * srcR + 197 * srcG + 48 * srcB) >> 8;
            dstG = (89 * srcR + 176 * srcG + 43 * srcB) >> 8;
            dstB = (70 * srcR + 137 * srcG + 34 * srcB) >> 8;
            dstR = dstR > 255 ? 255 : dstR;
            dstG = dstG > 255 ? 255 : dstG;
            dstB = dstB > 255 ? 255 : dstB;
            q0[3 * j] = dstR;
            q0[3 * j + 1] = dstG;
            q0[3 * j + 2] = dstB;
        }
    }
    imshow("老照片", dst_img);
    waitKey();
    return 0;
}

在这里插入图片描述

7.1.2 红绿互换

红绿互换是指红色通道与绿色通道进行交换。

cvtColor(dst_img, dst_img, COLOR_RGB2BGR);

在这里插入图片描述
此图片是老照片的红绿通道进行了交换。

7.1.3 灰度

  cvtColor(src_img, dst_img, COLOR_RGB2GRAY);

在这里插入图片描述

7.1.4 二值化

   cvtColor(src_img, dst_img, COLOR_RGB2GRAY);
   threshold(dst_img, dst_img, 128, 255, 0);

在这里插入图片描述

7.1.5 颜色变换

在这里插入图片描述

7.1.6 颜色通道

R通道:

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst[3];
    Mat dstR(src_img.rows, src_img.cols, CV_8UC1);
    split(src_img, dst);
    dst[0].copyTo(dstR);
    imshow("R通道", dstR);
    waitKey();
    return 0;
}


G通道:
在这里插入图片描述

B通道:
在这里插入图片描述

7.2 手工画

7.2.1 木雕

将图像处理为木雕效果,可以将图像的轮廓以白色显示。

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst(src_img.rows,src_img.cols,CV_8UC1);
    Mat src;
    cvtColor(src_img, src, COLOR_RGB2GRAY);
    for (int i = 1; i < src.rows - 1; i++)
    {
        uchar *current = src.ptr<uchar>(i);
        uchar *currentBefore = src.ptr<uchar>(i - 1);
        uchar* currentNext = src.ptr<uchar>(i + 1);
        uchar* dstLine = dst.ptr<uchar>(i);
        for (int j = 1; j < src.cols - 1; j++)
        {
            int a, b, c, d, e, f, g, h;
            a = abs(current[j] - currentBefore[(j - 1)]);
            b = abs(current[j] - currentBefore[j]);
            c = abs(current[j] - currentBefore[(j + 1)]);
            d = abs(current[j] - currentNext[(j - 1)]);
            e = abs(current[j] - currentNext[(j)]);
            f = abs(current[j] - currentNext[(j + 1)]);
            g = abs(current[j] - current[(j - 1)]);
            h = abs(current[j] - current[(j + 1)]);
            if (a > 30 || b > 30 || c > 30 || d > 30 || e > 30 || f > 30 || g > 30 || h > 30)
                dstLine[j] = 255;
            else
                dstLine[j] = 0;
        }
    }
    imshow("木雕", dst);
    waitKey();
    return 0;
}

在这里插入图片描述

7.2.2 铅笔画

将图像处理为铅笔画效果,可以将图像的轮廓以黑色显示。
在这里插入图片描述

7.2.3 素描

素描的处理过程为:首先将原始图像进行灰度化、反色处理得到一个图像ImgINV,再将原始图像进行高斯处理得到图像imgGauss,对上述图像进行处理如下:
在这里插入图片描述
在这里插入图片描述

7.3 艺术效果

7.3.1 连环画

连环画效果是将当前像素点的R通道、G通道、B通道分别进行算数运算后再进行灰度化。
在这里插入图片描述

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst(src_img.size(), CV_8UC3);
    for (int y = 0; y < src_img.rows ; y++)
    {
        uchar* srcR = src_img.ptr<uchar>(y);
        uchar* dstR = dst.ptr<uchar>(y);
        int br, bg, bb;
        float brF, bgF, bbF;
        for (int x = 0; x < src_img.cols ; x++)
        {
            br = srcR[3 * x];
            bg = srcR[3 * x + 1];
            bb = srcR[3 * x + 2];
           
            brF = (abs(bg - bb + bg + br) * br) >> 8;
            bgF = (abs(bb - bg + bb + br) * br) >> 8;
            bbF = (abs(bb - bg + bb + br) * bg) >> 8;

            brF = brF > 255 ? 255 : brF;
            bgF = bgF > 255 ? 255 : bgF;
            bbF = bbF > 255 ? 255 : bbF;
            
            brF = brF < 0 ? 0 : brF;
            bgF = bgF < 0 ? 0 : bgF;
            bbF = bbF < 0 ? 0 : bbF;

            dstR[3 * x] =(uchar) brF;
            dstR[3 * x + 1] =(uchar) bgF;
            dstR[3 * x + 2] =(uchar) bbF;
        }
    }
    cvtColor(dst, dst, COLOR_BGR2GRAY);//灰度化
    normalize(dst, dst, 255, 0, NORM_MINMAX);//归一化函数
    imshow("连环画", dst);
    waitKey();
    return 0;
}

在这里插入图片描述

7.3.2 熔铸

在这里插入图片描述

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst(src_img.size(), CV_8UC3);
    for (int y = 0; y < src_img.rows ; y++)
    {
        uchar* srcR = src_img.ptr<uchar>(y);
        uchar* dstR = dst.ptr<uchar>(y);
        int br, bg, bb;
        for (int x = 0; x < src_img.cols ; x++)
        {
            br = srcR[3 * x];
            bg = srcR[3 * x + 1];
            bb = srcR[3 * x + 2];
           
            br = br * 128 / (bg + bb + 1);
            bg = bg * 128 / (br + bb + 1);
            bb = bb * 128 / (bg + br + 1);

            br = br > 255 ? 255 : br;
            bg = bg > 255 ? 255 : bg;
            bb = bb > 255 ? 255 : bb;
            
            br = br < 0 ? 0 : br;
            bg = bg < 0 ? 0 : bg;
            bb = bb < 0 ? 0 : bb;

            dstR[3 * x] = br;
            dstR[3 * x + 1] = bg;
            dstR[3 * x + 2] = bb;
        }
    }
    imshow("熔铸", dst);
    waitKey();
    return 0;
}

在这里插入图片描述

7.3.3 冷冻

在这里插入图片描述

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst(src_img.size(), CV_8UC3);
    for (int y = 0; y < src_img.rows ; y++)
    {
        uchar* srcR = src_img.ptr<uchar>(y);
        uchar* dstR = dst.ptr<uchar>(y);
        float br, bg, bb;
        for (int x = 0; x < src_img.cols ; x++)
        {
            br = srcR[3 * x];
            bg = srcR[3 * x + 1];
            bb = srcR[3 * x + 2];
           
            br = (br - bg - bb) * 3 / 2;
            bg = (bg - br - bb) * 3 / 2;
            bb = (bb - bg - br) * 3 / 2;

            br = br > 255 ? 255 : br;
            bg = bg > 255 ? 255 : bg;
            bb = bb > 255 ? 255 : bb;
            
            br = br < 0 ? -br : br;
            bg = bg < 0 ? -bg : bg;
            bb = bb < 0 ? -bb : bb;

            dstR[3 * x] =(uchar) br;
            dstR[3 * x + 1] =(uchar) bg;
            dstR[3 * x + 2] =(uchar) bb;
        }
    }
    imshow("冷冻", dst);
    waitKey();
    return 0;
}

在这里插入图片描述

7.4 光线

7.4.1反相

反相效果的处理是用255减去当前像素点的像素值,将计算结果作为当前像素点的像素值。

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst(src_img.size(), CV_8UC3);
    for (int y = 0; y < src_img.rows ; y++)
    {
        uchar* srcR = src_img.ptr<uchar>(y);
        uchar* dstR = dst.ptr<uchar>(y);
        int br, bg, bb;
        for (int x = 0; x < src_img.cols ; x++)
        {
            br = srcR[3 * x];
            bg = srcR[3 * x + 1];
            bb = srcR[3 * x + 2];
          
            dstR[3 * x] = 255 - br;
            dstR[3 * x + 1] = 255 - bg;
            dstR[3 * x + 2] = 255 - bb;
        }
    }
    imshow("反相", dst);
    waitKey();
    return 0;
}

在这里插入图片描述

7.4.2 黑白底片

黑白底片是将图像进行反相后进行灰度化处理。
在这里插入图片描述

7.5 雕刻

7.5.1 凸雕

实现凸雕时,使用右下角的点减去左上角的点。、

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst(src_img.size(), CV_8UC3);
    for (int i = 1; i < src_img.rows - 1 ; i++)
    {
        uchar* current = src_img.ptr<uchar>(i);
        uchar* currentBefore = src_img.ptr<uchar>(i-1);
        uchar* dstLine = dst.ptr<uchar>(i);
        for (int j = 1; j < src_img.cols - 1; j++)
        {
            for (int k = 0; k < 3; k++)
            {
                int tmp0 = current[3 * j + k] - currentBefore[3 * (j - 1) + k] + 128;
                if (tmp0 < 0)
                    dstLine[3 * j + k] = 0;
                else if (tmp0 > 255)
                    dstLine[3 * j + k] = 255;
                else
                    dstLine[3 * j + k] = tmp0;
            }
        }
    }
    imshow("凸雕", dst);
    waitKey();
    return 0;
}

在这里插入图片描述

·

7.5.2 凹雕

实现凹雕时,使用左上角的点减去右下角的点。

#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;//包含cv命名空间
int main()
{
    //读入原始图像
    Mat src_img = imread("cat1.jpg");
    imshow("原始图像", src_img);
    Mat dst(src_img.size(), CV_8UC3);
    for (int i = 1; i < src_img.rows - 1 ; i++)
    {
        uchar* current = src_img.ptr<uchar>(i);
        uchar* currentBefore = src_img.ptr<uchar>(i-1);
        uchar* dstLine = dst.ptr<uchar>(i);
        for (int j = 1; j < src_img.cols - 1; j++)
        {
            for (int k = 0; k < 3; k++)
            {
                int tmp0 = current[3 * (j - 1) + k] - currentBefore[3 * j + k] + 128;
                if (tmp0 < 0)
                    dstLine[3 * j + k] = 0;
                else if (tmp0 > 255)
                    dstLine[3 * j + k] = 255;
                else
                    dstLine[3 * j + k] = tmp0;
            }
        }
    }
    imshow("凹雕", dst);
    waitKey();
    return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值