思路:原图像以灰度图形式进行读取,然后将图像进行缩小,再根据图像的像素值(0~255)确定要替换的目标图像,比如0~25替换为数字0图像,26~50替换为数字1图像。按行扫描确定替换的图像,把替换的图像与预设行图像进行水平拼接,形成图像的行,整行扫描完再图像的行塞入大图中,这样一行行的形成最终大图。
目录
原图像:
一、图像读取
数字图像按path/number.jpg形式存放,因此读取时只需替换路径中number变量。然后由于数字图像尺寸为28*28,需要进行缩小(20*20),并且塞入图像向量中。代码实现如下:
string path = "/home/ghoson-x/Desktop/qt/",FilePost = ".jpg";
for(int i=1;i<=10;++i){
string * ImgPath = new string;
Mat image;
ImgPath->append(path).append(QString::number(i).toStdString()).append(FilePost);
cout << "Path: " << ImgPath->data() << endl;
Mat tmp = imread(ImgPath->data(),IMREAD_GRAYSCALE);
cv::resize(tmp,image,Size(20,20));
images.push_back(image);
delete ImgPath;
}
二、原图像预处理
将图像转为灰度图、然后进行均值模糊,再进行尺寸缩小。
cvtColor(src,src,COLOR_BGR2GRAY);
kernel = getStructuringElement(MORPH_RECT,Size(3,3));
medianBlur(src,src,3);
cv::resize(src,dst,Size(src.cols/3,src.rows/3));
三、确定目标图像尺寸
由于数字图像尺寸为20*20,因此目标图像高为行数*20,宽为列数*20.
四、确定像素替换的图像
因为0~255对应数字0~9十个数,因此将像素值除以25即可一一对应,针对250~255,其运算结果为10,将其视为9替换图像。
int num = (dst.at<uchar>(j,k))/25;
if(num==10){
num = 9;}
五、水平拼接
行图像初始化
Mat ImgRow;
ImgRow.push_back(images[0]);
每扫描一个像素水平拼接一次
hconcat(ImgRow,images[size_t(num)],ImgRow);
六、垂直拼接
列初始化
if(j==0){
Mat initImg = Mat::zeros(ImgRow.rows,ImgRow.cols,CV_8U);
Imgcol.push_back(initImg);
}
每扫描完一行垂直拼接一次
vconcat(Imgcol,ImgRow,Imgcol);
七、显示目标图像
namedWindow("newimg",WINDOW_NORMAL);
cv::imwrite("/home/ghoson-x/Desktop/qt/result.jpg",Imgcol);
imshow("newimg",Imgcol);
注意:在进行水平拼接时要考虑初始化的矩阵是空的,而水平拼接函数要求两个图像高度相同,因此本文在初始化行图像时进数字0矩阵塞入其中,以便水平拼接函数的实现。