2017-04-27 09:54:10 guduruyu 阅读数 60607
  • FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK

    FFMpeg是当今为的面向音视频开发的开源工程,广泛应用于多种音视频的客户端、播放器和流媒体服务器中。使用FFMpeg提供的工具和SDK,可以完成音视频的编码、解码、转码、封装、解封装、转封装、视频水印和视频缩放等多种需求的开发。

    43972 人正在学习 去看看 殷汶杰

图像的几何变换,如缩放、旋转和翻转等,在图像处理中扮演着重要的角色,python中的Image类分别提供了这些操作的接口函数,下面进行逐一介绍。


1、图像的缩放

图像的缩放使用resize()成员函数,直接在入参中指定缩放后的尺寸即可,示例如下:

#-*- coding: UTF-8 -*- 

from PIL import Image

#读取图像
im = Image.open("lenna.jpg")
im.show()

#原图像缩放为128x128
im_resized = im.resize((128, 128))
im_resized.show()


变换结果如下:



2、图像的旋转

图像的旋转使用成员函数rotate(),在入参中直接指定按逆时针旋转的角度即可,示例如下:

#-*- coding: UTF-8 -*- 

from PIL import Image

#读取图像
im = Image.open("lenna.jpg")
im.show()

# 指定逆时针旋转的角度
im_rotate = im.rotate(45) 
im_rotate.show()


变换结果如下:

3、图像的翻转

图像的翻转使用transpose()成员函数,直接在入参中指定变换方式即可,不仅支持上下、左右翻转;也支持逆时针90、180、270等角度的旋转,效果与rotate()相同。示例如下:

out = im.transpose(Image.FLIP_LEFT_RIGHT)
out = im.transpose(Image.FLIP_TOP_BOTTOM)
out = im.transpose(Image.ROTATE_90)
out = im.transpose(Image.ROTATE_180)
out = im.transpose(Image.ROTATE_270)


变换结果如下:



2017.04.27

2016-08-12 15:12:59 scimence 阅读数 3779
  • FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK

    FFMpeg是当今为的面向音视频开发的开源工程,广泛应用于多种音视频的客户端、播放器和流媒体服务器中。使用FFMpeg提供的工具和SDK,可以完成音视频的编码、解码、转码、封装、解封装、转封装、视频水印和视频缩放等多种需求的开发。

    43972 人正在学习 去看看 殷汶杰

示例:

Image screen = getScreen();                       // 截取屏幕
saveImage(screen, screen.Size, @"d:\截屏.jpg");   // 保存截屏

# region 图像处理功能函数

/// <summary>
/// 按指定尺寸对图像pic进行非拉伸缩放
/// </summary>
public static Bitmap shrinkTo(Image pic, Size S, Boolean cutting)
{
    //创建图像
    Bitmap tmp = new Bitmap(S.Width, S.Height);     //按指定大小创建位图

    //绘制
    Graphics g = Graphics.FromImage(tmp);           //从位图创建Graphics对象
    g.Clear(Color.FromArgb(0, 0, 0, 0));            //清空

    Boolean mode = (float)pic.Width / S.Width > (float)pic.Height / S.Height;   //zoom缩放
    if (cutting) mode = !mode;                      //裁切缩放

    //计算Zoom绘制区域             
    if (mode)
        S.Height = (int)((float)pic.Height * S.Width / pic.Width);
    else
        S.Width = (int)((float)pic.Width * S.Height / pic.Height);
    Point P = new Point((tmp.Width - S.Width) / 2, (tmp.Height - S.Height) / 2);

    g.DrawImage(pic, new Rectangle(P, S));

    return tmp;     //返回构建的新图像
}


//保存图像pic到文件fileName中,指定图像保存格式
public static void SaveToFile(Image pic, string fileName, bool replace, ImageFormat format)    //ImageFormat.Jpeg
{
    //若图像已存在,则删除
    if (System.IO.File.Exists(fileName) && replace)
        System.IO.File.Delete(fileName);

    //若不存在则创建
    if (!System.IO.File.Exists(fileName))
    {
        if (format == null) format = getFormat(fileName);   //根据拓展名获取图像的对应存储类型

        if (format == ImageFormat.MemoryBmp) pic.Save(fileName);
        else pic.Save(fileName, format);                    //按给定格式保存图像
    }
}

//根据文件拓展名,获取对应的存储类型
public static ImageFormat getFormat(string filePath)
{
    ImageFormat format = ImageFormat.MemoryBmp;
    String Ext = System.IO.Path.GetExtension(filePath).ToLower();

    if (Ext.Equals(".png")) format = ImageFormat.Png;
    else if (Ext.Equals(".jpg") || Ext.Equals(".jpeg")) format = ImageFormat.Jpeg;
    else if (Ext.Equals(".bmp")) format = ImageFormat.Bmp;
    else if (Ext.Equals(".gif")) format = ImageFormat.Gif;
    else if (Ext.Equals(".ico")) format = ImageFormat.Icon;
    else if (Ext.Equals(".emf")) format = ImageFormat.Emf;
    else if (Ext.Equals(".exif")) format = ImageFormat.Exif;
    else if (Ext.Equals(".tiff")) format = ImageFormat.Tiff;
    else if (Ext.Equals(".wmf")) format = ImageFormat.Wmf;
    else if (Ext.Equals(".memorybmp")) format = ImageFormat.MemoryBmp;

    return format;
}

[DllImport("user32.dll")]
static extern bool GetCursorInfo(out CURSORINFO pci);

private const Int32 CURSOR_SHOWING = 0x00000001;
[StructLayout(LayoutKind.Sequential)]
struct POINT
{
    public Int32 x;
    public Int32 y;
}

[StructLayout(LayoutKind.Sequential)]
struct CURSORINFO
{
    public Int32 cbSize;
    public Int32 flags;
    public IntPtr hCursor;
    public POINT ptScreenPos;
}

/// <summary>
/// 截取屏幕指定区域为Image,保存到路径savePath下,haveCursor是否包含鼠标
/// </summary>
public static Image getScreen(int x = 0, int y = 0, int width = -1, int height = -1, String savePath = "", bool haveCursor = true)
{
    if (width == -1) width = SystemInformation.VirtualScreen.Width;
    if (height == -1) height = SystemInformation.VirtualScreen.Height;

    Bitmap tmp = new Bitmap(width, height);                 //按指定大小创建位图
    Graphics g = Graphics.FromImage(tmp);                   //从位图创建Graphics对象
    g.CopyFromScreen(x, y, 0, 0, new Size(width, height));  //绘制

    // 绘制鼠标
    if (haveCursor)
    {
        try
        {
            CURSORINFO pci;
            pci.cbSize = Marshal.SizeOf(typeof(CURSORINFO));
            GetCursorInfo(out pci);
            System.Windows.Forms.Cursor cur = new System.Windows.Forms.Cursor(pci.hCursor);
            cur.Draw(g, new Rectangle(pci.ptScreenPos.x, pci.ptScreenPos.y, cur.Size.Width, cur.Size.Height));
        }
        catch (Exception ex) { }    // 若获取鼠标异常则不显示
    }

    //Size halfSize = new Size((int)(tmp.Size.Width * 0.8), (int)(tmp.Size.Height * 0.8));  // 按一半尺寸存储图像
    if (!savePath.Equals("")) saveImage(tmp, tmp.Size, savePath);       // 保存到指定的路径下

    return tmp;     //返回构建的新图像
}

/// <summary>
/// 缩放icon为指定的尺寸,并保存到路径PathName
/// </summary>
public static void saveImage(Image image, Size size, String PathName)
{
    Image tmp = shrinkTo(image, size, false);
    SaveToFile(tmp, PathName, true, null);
}

# endregion



2019-04-07 17:57:24 lena_bmp 阅读数 103
  • FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK

    FFMpeg是当今为的面向音视频开发的开源工程,广泛应用于多种音视频的客户端、播放器和流媒体服务器中。使用FFMpeg提供的工具和SDK,可以完成音视频的编码、解码、转码、封装、解封装、转封装、视频水印和视频缩放等多种需求的开发。

    43972 人正在学习 去看看 殷汶杰

#用Visual C++实现图像双线性插值法等比例缩放
  在数字图像处理中,图像的缩放是基本的操作。下面介绍利用Visual C++ MFC多文档应用程序对话框,基于双线性插值法来实现图像缩放的功能,本实验采用Visual Studio 2017完成。
  MFC多文档应用程序的建立步骤略,代码中已经提前加入了图像的读取功能(在Doc类中,可在大部分Visual C++数字图像处理参考书中找到源代码)。
  先添加一个对话框,在资源视图中右键点击menu,点击插入dialog即可
  插入的对话框最好改一下ID,比如我这里叫ID_Zoom。再向其中添加一个Edit Control控件用于输入缩放比例因子,同样最好修改一下ID(我这里叫IDC_Ratio),旁边再加一个static text文本框用作说明。在这里插入图片描述
  然后需要为该对话框添加一个类,类名自定。基类可选择CDialog或CDialogEx,后者是前者的扩展类,具有CDialog的全部功能和一些新功能,这里我选择的是CDialog。
  创建完成后在该对话框类的头文件中加入成员变量Zoom,为缩放比例,类型为double。关于为新创建的类添加成员变量和成员函数,既可以直接在类的头文件中声明,也可以用类向导创建。由于前一种方法需要自行添加消息响应,比较麻烦,因此推荐直接利用类向导添加,方法为右键点击对话框空白处,选择添加变量,在弹出的“添加控件变量”对话框中为相应的控件(此处为IDC_Ratio,即Edit Control控件)添加变量,记得将“类别”设置为“值”,变量类型改为double
  下一步在资源视图menu中添加相应事件,并为其添加事件处理程序在这里插入图片描述
处理程序选择View类的command类型,点击添加编辑
  接下来就开始正式编写程序。
在这里插入图片描述
  首先要明白一点,位图作为若干个像素点的集合,在缩放过程中不可避免地会产生像素点的增加或减少。以放大为例,假如放大两倍则会多出原来图像三倍的像素点。这些多出来的像素点如何进行填充?基本的方法是把处理后的图片向原图进行映射,也成为向后映射,比如原图中一个点的位置为(5,4),在放大2倍后的图像中的坐标就变成了(10,8)。把放大后的图片中的任意一个像素点向原图映射,如放大2倍后的图片中某一像素点A坐标为A(15,9),则该像素点在原图中对应的坐标即B(7.5,4.5)。但我们知道像素坐标都是BYTE(或unsigned char)类型,不会出现小数值,因此就需要用B周围的点的灰度值来进行相应运算作为A点的灰度值。一种方法是最邻近插值法,也就是说计算一下B点离哪个像素点最近,则直接把该像素点的灰度值赋给B,但是由于该方法过于简单粗暴,因此获得的图像往往不够清晰;另一种方法——双线性插值法则较好地解决了这一问题,它的基本思想是将B点周围的四个像素点按权计算灰度赋给A点。权值的选取取决于距离的远近,离B点越近的点计算灰度权重最大。以下是一个双线性插值原理的示意图,生动形象。
  在这里插入图片描述
  计算方法如下:若某一向后映射点C(4.1,5.7),它周围的四个点为C1(4,5)、C2(4.6)、C3(5,5)、C4(5,6)。在纵向上,C点离C1、C2较近,离C3、C4较远,距离比为1:9,那么对应的C点原映射点的灰度值就应该等于C1、C2综合起来的灰度值gray12和C3、C4综合的灰度值gray34乘以0.9和0.1两个权值所得值,至于这个gray12和gray34怎么计算,则还是同样的方法。根据C点离C1、C2的距离l1、l2可按权计算出gray12=(gray1l2+gray2l1)/(l1+l2)。因此不难看出该方法通过两次权值线性分配来计算灰度值,因此得名双线性插值法。
接下来就是快乐的代码实现过程。由于之前我已经在Doc类头文件中声明过一些变量,此处直接用Doc类指针调用其中的数据。
这是代码中调用的头文件的成员变量

void CMFCApplication7View::OnZoom()
{
	// TODO: 在此添加命令处理程序代码
	ZoomDlg cgt;

	if (cgt.DoModal())//判断是否打开模式对话框。如果不调用对话框的DoModal方法,点击menu里添加的图像缩放后,之前创建的对话框ID_Ratio就不会弹出来
	{
		CMFCApplication7Doc *pDoc = GetDocument();

		ASSERT_VALID(pDoc);

		UINT outWidth;
		UINT outHeight;
	
		//pDoc->imageWidth = (UINT)(1.0*pDoc->imageWidth / 4.0 + 0.5) * 4;
		//pDoc->lpbmi->bmiHeader.biWidth = pDoc->imageWidth;

		UINT inWidth = pDoc->imageWidth;
		UINT inHeight = pDoc->imageHeight;
		UINT inSize = inWidth * inHeight;	

		outWidth = (UINT)(1.0*inWidth* cgt.Zoom / 4.0 + 0.5) * 4;
		outHeight = (UINT)(1.0*inHeight* cgt.Zoom + 0.5);//宽高为缩放后的图像宽高
		UINT outSize = outWidth * outHeight;

		int i, j;
		
		unsigned char * pBits = pDoc->m_pBits;
		unsigned char * pOldBits;

		pDoc->lpbmi->bmiHeader.biWidth = outWidth;
		pDoc->lpbmi->bmiHeader.biHeight = outHeight;
		pDoc->imageWidth = outWidth;
		pDoc->imageHeight = outHeight;

		if (pDoc->m_nColorBits == 8)
		{		
			pOldBits = new unsigned char[inSize];
			if (pOldBits == NULL)
				return;

			memcpy(pOldBits, pBits, inSize);//把原图像中的数据拷贝到pOldBits里

			delete[] pBits;	

			pBits = new unsigned char[outSize];
			if (pBits == NULL)
				return;

			pDoc->m_pBits = pBits;
			memset(pBits, 0, outSize);

			for ( j = 0; j < outHeight ; j++)
			{
				for ( i = 0; i < outWidth ; i++)
				{ 
					double x = 1.0*i / cgt.Zoom;
					double y = 1.0*j / cgt.Zoom;

					int x1, x2, y1, y2;//原图中映射点周围四个点的坐标

					x1 = (int)x;//左x
					x2 = x1 + 1;//右x					
					y1 = (int)y;//上y
					y2 = y1 + 1;//下y
					/*
					  x1、y1始终不会越界
					  x2、y2可能越界
					  因此须对x2、y2越界的情况单独讨论
					 */

					BYTE clr1, clr2, clr3, clr4;
					double u, v;
					u = x - x1;
					v = y - y1;
					
					if (i == outWidth - 1&& j== outHeight-1)//右下顶点
						pBits[j*outWidth + i] = pOldBits[y1*inWidth + inWidth - 1];
					else if(i==outWidth-1)//第一列除右下顶点部分
						{
							clr1 = pOldBits[y1*inWidth + x1];//左上
							clr3 = pOldBits[y2*inWidth + x1];//左下
							pBits[j*outWidth + i] = (BYTE)clr1 * (1 - v) + clr3 * v;
						}			
					else if (j == outHeight - 1)//最后一行除右下顶点部分
					{
							clr1 = pOldBits[y1*inWidth + x1];//左上
							clr2 = pOldBits[y1*inWidth + x2];//右上

							pBits[j*outWidth + i] = (BYTE)(clr1 * (1 - u) + clr2 * u);
					}
					else//其他部分
					{	
							clr1 = pOldBits[y1*inWidth + x1];//左上
							clr2 = pOldBits[y1*inWidth + x2];//右上
							clr3 = pOldBits[y2*inWidth + x1];//左下
							clr4 = pOldBits[y2*inWidth + x2];//右下

							pBits[j*outWidth + i] = (BYTE)((u*clr2 + (1 - u)*clr1)*(1 - v) + (u*clr3 + (1 - u)*clr4)*v);					
					}//end else					
				}//for(i = 0 ……)
			}//for(j = 0 ……)	

			Invalidate();
			delete pOldBits;//删除零时分配内存
			return;

		}	//结束m_pBits=8判定	

		
			
		if (pDoc->m_nColorBits == 24)
			{
				pOldBits = new unsigned char[inSize * 3];
					if (pOldBits == NULL)
						return;

				memcpy(pOldBits, pBits, inSize * 3);//把原图像中的数据拷贝到pOldBits里

				delete[] pBits;

				pBits = new unsigned char[outSize * 3];
				
				if (pBits == NULL)
					return;
			
				pDoc->m_pBits = pBits;
				memset(pBits, 0, outSize * 3);

				for (int k = 0; k < 3; k++)
					{
						for (j = 0; j < outHeight; j++)
								{
									for (i = 0; i < outWidth; i++)
										{
											double x = 1.0*i / cgt.Zoom;
											double y = 1.0*j / cgt.Zoom;

											int x1, x2, y1, y2;//原图中映射点周围四个点的坐标

											x1 = (int)x;//左x
											x2 = x1 + 1;//右x					
											y1 = (int)y;//上y
											y2 = y1 + 1;//下y

											BYTE clr1, clr2, clr3, clr4;
											double u, v;
											u = x - x1;
											v = y - y1;

											if (i == outWidth - 1 && j == outHeight - 1)//右下顶点
												pBits[(j*outWidth + i) * 3 + k] = pOldBits[(y1*inWidth + inWidth - 1) * 3 + k];
											else if (i == outWidth - 1)//最后一列除右下顶点部分
												{
													clr1 = pOldBits[(y1*inWidth + x1) * 3 + k];//左上
													clr3 = pOldBits[(y2*inWidth + x1) * 3 + k];//左下
													pBits[(j*outWidth + i) * 3 + k] = (BYTE)(clr1 * (1 - v) + clr3 * v);
												}
											else if (j == outHeight - 1)//最后一行除右下顶点部分
												{
													clr1 = pOldBits[(y1*inWidth + x1) * 3 + k];//左上
													clr2 = pOldBits[(y1*inWidth + x2) * 3 + k];//右上
													pBits[(j*outWidth + i) * 3 + k] = (BYTE)(clr1 * (1 - u) + clr2 * u);
												}
											else//其他部分
												{
													clr1 = pOldBits[(y1*inWidth + x1) * 3 + k];//左上
													clr2 = pOldBits[(y1*inWidth + x2) * 3 + k];//右上
													clr3 = pOldBits[(y2*inWidth + x1) * 3 + k];//左下
													clr4 = pOldBits[(y2*inWidth + x2) * 3 + k];//右下

													pBits[(j*outWidth + i) * 3 + k] = (BYTE)((u*clr2 + (1 - u)*clr1)*(1 - v) + (u*clr3 + (1 - u)*clr4)*v);
												}//end else
									}//for(i = 0 ……)
						}//for(j = 0 ……)		
				}	//三重循环分别处理三个分量		
					Invalidate();
					delete pOldBits;//删除零时分配内存
					return;
		}//结束m_pBits=24判定
	}//DoModal						
	else
		return;
}

运行一下看看(又是辣个熟悉的女人)
在这里插入图片描述
  放大1.5倍后:
在这里插入图片描述在这里插入图片描述
  利用双线性插值法完成对话框图像缩放应用程序完成!
  如有错漏,恳请指正!

2017-07-31 20:07:12 pianzang5201 阅读数 476
  • FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK

    FFMpeg是当今为的面向音视频开发的开源工程,广泛应用于多种音视频的客户端、播放器和流媒体服务器中。使用FFMpeg提供的工具和SDK,可以完成音视频的编码、解码、转码、封装、解封装、转封装、视频水印和视频缩放等多种需求的开发。

    43972 人正在学习 去看看 殷汶杰

扩展缩放只是改变图像的尺寸大小。OpenCV 提供的函数 cv2.resize()可以实现这个功能。图像的尺寸可以自己手动设置,你也可以指定缩放因子。我 们可以选择使用不同的插值方法。在缩放时我们推荐使用cv2.INTER_AREA, 在扩展时我们推荐使用v2.INTER_CUBIC(慢)v2.INTER_LINEAR。 默认情况下所有改变图像尺寸大小的操作使用的插值方法都是cv2.INTER_LINEAR。 使用方法cv2.resize(src, dst, interpolation=CV_INTER_LINEAR)


import cv2
import numpy as np

img = cv2.imread('F:/beauty.jpg')
#第一种方法
#下面的None本应该是输出的图像尺寸,但是因为后面设置了缩放因子,所以这里设置了None
res = cv2.resize(img, None, fx = 2, fy = 2, interpolation = cv2.INTER_CUBIC)
#第二种方法
#直接设置输出图像的高宽值,所以没有设置缩放因子
height, width = img.shape[:2]
res = cv2.resize(img, (2*width, 2*height), interpolation = cv2.INTER_CUBIC)

while(1):
    cv2.imshow('res', res)
    cv2.imshow('img', img)

    if cv2.waitKey(1)&0xFF==27:
        break
cv2.destroyAllWindows()


结果图:



2016-11-09 15:26:14 u012428169 阅读数 356
  • FFMpeg视频开发与应用基础——使用FFMpeg工具与SDK

    FFMpeg是当今为的面向音视频开发的开源工程,广泛应用于多种音视频的客户端、播放器和流媒体服务器中。使用FFMpeg提供的工具和SDK,可以完成音视频的编码、解码、转码、封装、解封装、转封装、视频水印和视频缩放等多种需求的开发。

    43972 人正在学习 去看看 殷汶杰

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

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

using namespace std;
using namespace cv;
/********************************************
void scale(Mat img, Mat &dst, double times)
功能: 图像的等比例缩放
注: 包括放大和缩小
参数: Mat img:原图像
       Mat dst:转置后图像
       double times: 缩放的倍数
返回值: 无
*********************************************/
void scale(Mat img, Mat &dst, double times)
{
    int nH = img.rows;
    int nW = img.cols;
    int dH = nH*times;
    int dW = nW*times;
    dst.create(dH, dW, img.type());
    int i, j;
    for (i = 0; i < dH; i++)
    {
        for (j = 0; j < dW; j++)
        {
            if (int(i/times + 0.5) < nH&&int(j/times + 0.5) < nW)
                dst.at<Vec3b>(i, j) = img.at<Vec3b>(int(i / times + 0.5), int(j / times + 0.5));
            else
                dst.at<Vec3b>(i, j) = 0;
        }
    }
}
int main()
{
    Mat img = imread("1.jpg");
    imshow("原图", img);
    Mat dst1;
    //缩放变换
    //scale(img, dst1,1.3);
    //imshow("缩放变换", dst1);
    waitKey(0);
    return 0;
}

结果图如下:
原图:
原图
放大1.3倍结果:
放大1.3倍
缩小0.8倍结果:
缩小0.8倍

图像缩放

阅读数 841

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