2016-11-08 17:10:41 u012428169 阅读数 611
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19558 人正在学习 去看看 夏曹俊

作为代码界的菜鸟,最近在尝试着用vs实现《数字图像处理与机器视觉》一书中有关图像处理的VC++代码。目前先从简单的图像几何变换做起,希望能记录自己的成长^_^
本篇是实现图像的镜像变换,包括水平镜像和垂直镜像。

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>

using namespace std;
using namespace cv;
/********************************************
void Mat horMirror(Mat img,Mat &dst)
功能: 图像的水平镜像
注: 图像左右镜像
参数: Mat img: 原图
      Mat dst: 水平镜像变换后图像
返回值: 无
*********************************************/
void horMirror(Mat img, Mat &dst)
{
    int nH = img.rows;
    int nW = img.cols;
    int i, j, u;
    for (i = 0; i < nW; i++)
    {
        u = nW - i - 1;
        for (j = 0; j < nH; j++)
        {
            dst.at<Vec3b>(j, i) = img.at<Vec3b>(j, u);
        }
    }
}
/********************************************
void Mat verMirror(Mat img,Mat &dst)
功能: 图像的垂直镜像
注: 图像上下镜像
参数: Mat img: 原图
      Mat dst: 垂直镜像变换后图像
返回值: 无
*********************************************/
void verMirror(Mat img, Mat &dst)
{
    int nH = img.rows;
    int nW = img.cols;
    int i, j, u = 0;
    for (i = 0; i < nH; i++)
    {
        u = nH - i - 1;
        for (j = 0; j < nW; j++)
            dst.at<Vec3b>(i, j) = img.at<Vec3b>(u, j);
    }
}
int main()
{
    Mat img = imread("1.jpg");
    imshow("原图", img);
    Mat dst=img.clone();    
    //水平镜像变换
    horMirror(img, dst);
    imshow("水平镜像变换", dst);
    //垂直镜像变换
    verMirror(img, dst);
    imshow("垂直镜像变换", dst);
}

结果图如下:
原图
水平镜像
垂直镜像

2017-04-01 15:52:50 linshanxian 阅读数 3146
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19558 人正在学习 去看看 夏曹俊

图像镜像分为水平镜像、垂直镜像和对角镜像三种:水平镜像是指将图像的左右部分以图像垂直中轴线为中心进行镜像对换;垂直镜像是将图像的上下两部分以图像水平中轴线为中心进行镜像对换;对角镜像是将图像以图像水平中轴线和垂直中轴线的交点为中心进行镜像对换,相当于将图像先后进行水平镜像和垂直镜像。下面具体阐述不同镜像的变换方法。

假设原图像的高度为h,宽度为w,变换后,图像的尺寸不变。那么原图像中(x0y0)经过水平镜像后坐标变为(w-1-x0y0)。用矩阵表示为:


逆变换为:



同理图像经过垂直镜像变换后的逆运算为


对角镜像的逆运算为:


主要代码如下:

void Mirror(const Mat &srcImage, Mat &dstImage, int flag)
{
    dstImage.create(srcImage.size(), srcImage.type());
    int nRowNum = srcImage.rows;
    int nColNum = srcImage.cols;
    switch(flag)
    {
    //水平镜像
    case 1:
        for(int i = 0; i < nRowNum; i++)
        {
            for(int j = 0; j < nColNum; j++)
            {
                dstImage.at<Vec3b>(i, j) = srcImage.at<Vec3b>(nRowNum - i - 1, j);
            }
        }
        break;
    //垂直镜像
    case 2:
        for(int i = 0; i < nRowNum; i++)
        {
            for(int j = 0; j < nColNum; j++)
            {
                dstImage.at<Vec3b>(i, j) = srcImage.at<Vec3b>(i, nColNum - j - 1);
            }
        }
        break;
    //对角镜像
    case 3:
        for(int i = 0; i < nRowNum; i++)
        {
            for(int j = 0; j < nColNum; j++)
            {
                dstImage.at<Vec3b>(i, j) = srcImage.at<Vec3b>(nRowNum - i - 1, nColNum - j - 1);
            }
        }
    }
}


2017-03-28 16:23:21 yunzhifeiti 阅读数 2219
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19558 人正在学习 去看看 夏曹俊

在图像处理中,镜像变换包括两种,关于Y轴镜像(即水平镜像)和关于X轴镜像(垂直镜像)

Y轴镜像(即水平镜像)就是在行不变的情况下,将图像的左右像素进行交换。以下代码适用于三通道图像。

代码如下:

void mirrorY(Mat src, Mat &dst)
{
    int row=src.rows;
    int col=src.cols;
    dst=src.clone();
    for (int i = 0; i < col; i++){
        srcImage.col(col - 1 - i).copyTo(dst.col(i));
    }
}
或者:

void mirrorY(Mat src, Mat &dst)
{
    int row=src.rows;
    int col=src.cols;
    dst=src.clone();
    for (int i = 0; i < row; i++){
	for (int j = 0; j < col; j++){
	dst.at<Vec3b>(i, j) = src.at<Vec3b>(i, col - 1 - j);
	}
    }
}
或者:

void mirrorY(Mat src, Mat &dst)
{
    int row=src.rows;
    int col=src.cols;
    dst=src.clone();
    Vec3b *origal3;
    for (int i = 0; i < row; i++){
	origal3 = src.ptr<Vec3b>(i);
	for (int j = 0; j < col; j++){
		dst.ptr<Vec3b>(i)[j] = origal3[col - 1 - j];
	}
    }
}
处理结果如图


X轴镜像(垂直镜像)就是在列不变的情况下,将图像的上下像素进行交换。代码如下:

void mirrorX(Mat src, Mat &dst)
{
    int row=src.rows;
    int col=src.cols;
    dst=src.clone();
    for (int i = 0; i < row; i++){
        srcImage.row(row - 1 - i).copyTo(dst.row(i));
    }
}

原理相同,同样可以对像素进行操作实现,此处不再赘述。


2014-04-11 14:32:17 flyxkh 阅读数 865
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19558 人正在学习 去看看 夏曹俊
简单的实现了三通道,1通道和别的通道类似
bool Mirror(Mat &img)
{
	if(!img.data)
		return false;
	unsigned char *pSrc = NULL,*pDst = NULL;
	int w = img.cols;
	int h = img.rows;
	int cn = img.channels();

	Mat img_mirror = img.clone();
	int wdt = (w-1)*cn;
	pSrc = img_mirror.data + wdt;
	pDst = img.data;
	switch (cn)
	{
	case 3:
		for (int y=0;y<h;y++)
		{
			for (int x=0;x<w*cn;x+=3)
			{
				*(pDst+x+0) = *(pSrc -x + 0);
				*(pDst+x+1) = *(pSrc -x + 1);
				*(pDst+x+2) = *(pSrc -x + 2);
			}
			pDst += w*cn;
			pSrc += w*cn;
		}
		break;
	case 1:

		break;
	default:
		break;
	}

	return true;
}

2013-07-10 21:33:18 liwuji930726 阅读数 1673
  • 学习OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频教程

    OpenCV3.2+QT5+ffmpeg实战开发视频编辑器视频培训课程概况:教程中会讲解到基于opencv视频和摄像机录制、播放和播放进度控制,多视频图像合并、多视频图像融合、剪切、视频亮度、对比度、尺寸(近邻插值(手动实现),双线性插值,图像金字塔)、颜色格式(灰度图,二值化(阈值)),旋转镜像,视频裁剪(ROI),视频水印(ROI+weight),导出处理后的视频(包含音频,使用ffmpeg工具对音频进行抽取、剪切和终于opencv处理的视频合并)。

    19558 人正在学习 去看看 夏曹俊

 镜像是两个物体关于中轴线对称的一种状态。

 图像的镜像分为两种:水平镜像、垂直镜像

 水平镜像:是将图像左半部分和右半部分以图像垂直中轴线为中心进行镜像对换

 垂直镜像:是将图像上半部分和下半部分以图像水平中轴线为中心进行镜像对换。

 

 算法描述:

 1)将源图像保存到缓冲区,并记录下缓冲区的地址。

 2)分配内存,以保存镜像后的图像。

 3)确定图像的镜像方式,是水平镜像还是垂直镜像。

 4)根据设定的镜像方式及源图中每个像素点的坐标值,计算出镜像后各像素点的新坐标值,实现图像的镜像。

 

 

/*************************************************************************
* 函数名称:Mirror(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
* 函数参数:
LPSTR lpSrcStartBits,指向DIB起始像素的指针
long lWidth,DIB图像的宽度
long lHeight,DIB图像的高度
long lLineBytes,DIB图像的行字节数,为4的倍数
* 函数类型:BOOL       
* 函数功能:该函数用来镜像DIB图像,本程序只实现了水平镜像,垂直镜像的原理书中也谈到。 很容易实现          
************************************************************************/

BOOL  Mirror(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)

 long i;                 //行循环变量
 long j;                 //列循环变量
 LPSTR lpSrcDIBBits; //指向源像素的指针
 LPSTR lpDstDIBBits; //指向临时图像对应像素的指针   
 HLOCAL hDstDIBBits; //临时图像句柄
 LPSTR lpBits; // 指向中间像素的指针,当复制图像时,提供临时的像素内存空间
 hDstDIBBits= LocalAlloc(LHND, lLineBytes);// 分配临时内存保存行图像
 if (hDstDIBBits == NULL)  
 {  
  return FALSE;         // 分配内存失败
 }  
 lpDstDIBBits= (char * )LocalLock(hDstDIBBits);// 锁定    
 for(i = 0; i < lHeight; i++)// 水平镜像,针对图像每行进行操作
 {   
  for(j = 0; j < lWidth / 2; j++)// 针对每行图像左半部分进行操作
  {       
   lpSrcDIBBits= (char *)lpSrcStartBits + lLineBytes * i + j;// 指向倒数第i行,第j个像素的指针        
   lpBits= (char *)lpSrcStartBits + lLineBytes * (i + 1) - j;// 指向倒数第i+1行,倒数第j个像素的指针        
   *lpDstDIBBits=*lpBits;//保存中间像素        
   *lpBits = *lpSrcDIBBits;// 将倒数第i行,第j个像素复制到倒数第i行,倒数第j个像素        
   *lpSrcDIBBits=*lpDstDIBBits;// 将倒数第i行,倒数第j个像素复制到倒数第i行,第j个像素
  }   
 }  
 LocalUnlock(hDstDIBBits);// 释放内存
 LocalFree(hDstDIBBits);
 return TRUE;
}

/*************************************************************************
* 函数名称:Mirror2(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)
* 函数参数:
LPSTR lpSrcStartBits,指向DIB起始像素的指针
long lWidth,DIB图像的宽度
long lHeight,DIB图像的高度
long lLineBytes,DIB图像的行字节数,为4的倍数
* 函数类型:BOOL       
* 函数功能:该函数用来垂直镜像DIB图像        
************************************************************************/

BOOL  Mirror2(LPSTR lpSrcStartBits, long lWidth, long lHeight,long lLineBytes)

 long i;                 //行循环变量
 long j;                 //列循环变量
 LPSTR lpSrcDIBBits; //指向源像素的指针
 LPSTR lpDstDIBBits; //指向临时图像对应像素的指针   
 HLOCAL hDstDIBBits; //临时图像句柄
 LPSTR lpBits; // 指向中间像素的指针,当复制图像时,提供临时的像素内存空间
 hDstDIBBits= LocalAlloc(LHND, lLineBytes);// 分配临时内存保存行图像
 if (hDstDIBBits == NULL)  
 {  
  return FALSE;         // 分配内存失败
 }  
 lpDstDIBBits= (char * )LocalLock(hDstDIBBits);// 锁定    
 for(i = 0; i < lHeight / 2; i++)// 垂直镜像,针对图像每行进行操作
 {   
  //for(j = 0; j < lWidth / 2; j++)// 针对每行图像左半部分进行操作
  //{       
  lpSrcDIBBits= (char *)lpSrcStartBits + lLineBytes * i ;//+ j;// 指向倒数第i行,第j个像素的指针        
  lpBits= (char *)lpSrcStartBits + lLineBytes * (lHeight - i + 1);// - j;// 指向倒数第i+1行,倒数第j个像素的指针        
  memcpy(lpDstDIBBits, lpBits, lLineBytes);
  memcpy(lpBits, lpSrcDIBBits, lLineBytes);
  memcpy(lpSrcDIBBits, lpDstDIBBits, lLineBytes);
  //*lpDstDIBBits=*lpBits;//保存中间像素        
  //*lpBits = *lpSrcDIBBits;// 将倒数第i行,第j个像素复制到倒数第i行,倒数第j个像素        
  //*lpSrcDIBBits=*lpDstDIBBits;// 将倒数第i行,倒数第j个像素复制到倒数第i行,第j个像素
  //}   
 }  
 LocalUnlock(hDstDIBBits);// 释放内存
 LocalFree(hDstDIBBits);
 return TRUE;
}

 

 VC编程实现(基于VS2010):

 

 

代码链接:点击打开链接

没有更多推荐了,返回首页