- 第六章 骰子作画学习系统
- 6.1 骰子状字块
- 6.1.1 设定大小
- 6.1.2 分类
- 6.1.3 赋值
- 6.2 原始图像特征值计算
- 6.3 映射
- 6.4 实验结果
- 第7章 滤镜效果学习系统
- 7.1颜色效果
- 7.1.1 老照片
- 7.1.2 红绿互换
- 7.1.3 灰度
- 7.1.4 二值化
- 7.1.5 颜色变换
- 7.1.6 颜色通道
- 7.2 手工画
- 7.2.1 木雕
- 7.2.2 铅笔画
- 7.2.3 素描
- 7.3 艺术效果
- 7.3.1 连环画
- 7.3.2 熔铸
- 7.3.3 冷冻
- 7.4 光线
- 7.4.1反相
- 7.4.2 黑白底片
- 7.5 雕刻
- 7.5.1 凸雕
- 7.5.2 凹雕
第六章 骰子作画学习系统
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;
}