最近遇到一个需要将图片进行动态显示的任务,图片的分辨率是320*2560,最开始的想法就是将图片看成一个320*2560大小的矩阵,然后定义一个320*320大小的小矩阵去遍历大矩阵,然后就用matlab实现了一下,感觉非常简单。
clear all
a=imread('E:\temp\r2.png');
b=im2bw(a);
% imwrite(b,'E:\temp\g.bmp');
m=zeros(320,320);
m1=double(b);
for i=1:2560
if i<=320
m(321-i,:)=m1(i,:);
else
for j=1:320
m(j,:)=m1(i+j-1,:);
end
p=logical(m);
imshow(p);
end
end
为了简化问题将图像进行了二值化,然后进行了遍历,因为,matlab的编程比较方便,所以就用了“:”运算符,但是想了想还是老实的用正经的语法吧
clear all
a=imread('E:\temp\r2.png');
b=im2bw(a);
% imwrite(b,'E:\temp\g.bmp');
m=zeros(320,320);
m1=double(b);
for k=1:2241
for i=1:320
for j=1:320
m(i,j)=m1(i+k-1,j);
end
end
imshow(m);
end
然后思考怎样在opencv中实现这样的想法,了解了IplImage方法可以运用,但是编程实现的时候遇到了问题,就是不能动态命名的问题,就是说我定义的字符串量不能直接转化成CvArr类型的。没有这样的构造函数,确实是这样,查看IplImage的数据结构发现在定义一个IplImage对象的时候已经有了相关的width,height,imageData,widthStep等等的空间,反正我自己是这么强行理解的。那只好把图像切割成16份了分别显示了。
#include "stdafx.h"
#include
#include
#include
#include
using namespace std;
int main(int argc, char* argv[])
{
IplImage *src = cvLoadImage("E:\\temp\\r2.png", 0);
cvNamedWindow("source", 1);
cvShowImage("source", src);
int m = src->height;
int n = src->width;
int i, j;
printf("channel = %d", src->nChannels);
// 分配内存
int **p;
p = new int *[m];
for (i = 0; i < m; i++)
{
p[i] = new int[n];
}
uchar *ptr;
for (i = 0; i < m; i++)
{
ptr = (uchar*)src->imageData + i*src->widthStep;
for (j = 0; j < n; j++)
{
p[i][j] = (int)*(ptr + j);
}
}
/**************************************/
IplImage *newImg = cvCreateImage(cvSize(320, 320), 8, 1);
//*********************第一帧***************************//
IplImage *copy1 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy1, i, j, p[i][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy1);
cvWaitKey(2000);
cvReleaseImage(©1);
//*********************第二帧***************************//
IplImage *copy2 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy2, i, j, p[i + 160][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy2);
cvWaitKey(1000);
cvReleaseImage(©2);
//*********************第三帧***************************//
IplImage *copy3 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy3, i, j, p[i + 160*2][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy3);
cvWaitKey(1000);
cvReleaseImage(©3);
//*********************第四帧***************************//
IplImage *copy4 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy4, i, j, p[i + 160 * 3][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy4);
cvWaitKey(1000);
cvReleaseImage(©4);
//*********************第五帧***************************//
IplImage *copy5 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy5, i, j, p[i +160 * 4][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy5);
cvWaitKey(1000);
cvReleaseImage(©5);
//*********************第六帧***************************//
IplImage *copy6 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy6, i, j, p[i + 160 * 5][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy6);
cvWaitKey(1000);
cvReleaseImage(©6);
//*********************第七帧***************************//
IplImage *copy7 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy7, i, j, p[i + 160 * 6][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy7);
cvWaitKey(1000);
cvReleaseImage(©7);
//*********************第八帧***************************//
IplImage *copy8 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy8, i, j, p[i + 160 * 7][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy8);
cvWaitKey(1000);
cvReleaseImage(©8);
//***********************9****************************//
IplImage *copy9 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy9, i, j, p[i + 160 * 8][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy9);
cvWaitKey(1000);
cvReleaseImage(©9);
//*******************************10************************//
IplImage *copy10 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy10, i, j, p[i + 160 * 9][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy10);
cvWaitKey(1000);
cvReleaseImage(©10);
//***********************11*************************//
IplImage *copy11 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy11, i, j, p[i + 160 * 10][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy11);
cvWaitKey(1000);
cvReleaseImage(©11);
//****************************12***********************//
IplImage *copy12 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy12, i, j, p[i + 160 * 11][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy12);
cvWaitKey(1000);
cvReleaseImage(©12);
//************************************13***************************//
IplImage *copy13 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy13, i, j, p[i + 160 * 12][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy13);
cvWaitKey(1000);
cvReleaseImage(©13);
//************************************14**************************************//
IplImage *copy14 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy14, i, j, p[i + 160 * 13][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy14);
cvWaitKey(1000);
cvReleaseImage(©14);
//************************************15*****************************//
IplImage *copy15 = cvCreateImage(cvGetSize(newImg), 8, 1);
for (i = 0; i < 320; i++)
{
for (j = 0; j < 320; j++)
{
cvSetReal2D(copy15, i, j, p[i + 160 * 14][j]);
}
}
// 显示图像副本
cvNamedWindow("copy", 1);
cvShowImage("copy", copy15);
cvWaitKey(0);
cvReleaseImage(©15);
// 释放图像
cvReleaseImage(&src);
cvDestroyAllWindows();
//释放内存
for (i = 0; i < m; i++)
delete[] p[i];
delete[] p;
return 0;
}
显示结果
但是这种结果真的不是我想要的,真是水平有限啊,但是后来又发现另外一种方法是基于Qt的图片显示的Pixmap方法
#include "MyWidget.h"
#include
#include
#include
MyWidget::MyWidget(QWidget *parent)
: QFrame(parent), m_times(0)
{
//m_picture.load("c:/qt.jpg");
m_picture.load("C:\\temp\\r2.png");
m_timerId = startTimer(60);
m_pressedNum = 0;
}
MyWidget::~MyWidget()
{
}
// 目标矩形按比例填充到源矩形, 返回实际的target位置
inline QRect scale(QRect source, QRect target)
{
int target_w = target.width();
int target_h = target.height();
int image_w = source.width();
int image_h = source.height();
if(image_w <= 0) image_w = 1;
if(image_h <= 0) image_h = 1;
int scaled_w = target_w;
int scaled_h = image_h * target_w / image_w;
if(scaled_h > target_h)
{
scaled_h = target_h;
scaled_w = target_h * image_w / image_h;
}
// 坐在中心
int x = (target_w - scaled_w)/2;
int y = (target_h - scaled_h)/2;
return QRect(x, y, scaled_w, scaled_h);
}
void MyWidget::paintEvent ( QPaintEvent * event )
{
QPainter painter(this);
int width = this->width();
int height = this->height();
//QRect target (0, 0, width/2, height/2); // 目标矩形
//QRect target (width/2, height/2, width/2, height/2); // 目标矩形
QRect target (0,0,width,height); // 目标矩形
int img_width = m_picture.width();
int img_height = m_picture.height();
if (m_times < 65)
{
QRect source(0, m_times*40, img_width, img_height / 8); // 源矩形
QRect scaled_target = scale(source, target);
painter.drawPixmap(scaled_target, m_picture, source);
m_times = m_times + 1;
}
return;
}
// 定时器处理函数
void MyWidget::timerEvent(QTimerEvent * event)
{
// 可以有多个定时器,每个的定时器有不同的处理
if (event->timerId() == m_timerId&&m_pressedNum % 2 == 1)
{
update(); // 重绘
}
}
void MyWidget::mouseReleaseEvent(QMouseEvent * event)
{
m_pressedNum = m_pressedNum+1;
}
这是.cpp文件,对应的.h文件
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include
#include //
#include
#include
class MyWidget : public QFrame
{
Q_OBJECT
public:
MyWidget(QWidget *parent);
~MyWidget();
private:
void paintEvent ( QPaintEvent * event );
void timerEvent(QTimerEvent * event);
void mouseReleaseEvent(QMouseEvent * event);
private:
QPixmap m_picture; //
int m_timerId; // 每个Timer有一个id
int m_times; // 次数
int m_pressedNum;
};
#endif // MYWIDGET_H
重写了paintEvent调用定时器来实现的
还增加了鼠标事件,实现点击一次播放,再点击停止,再点击再播放....