17.1 图像操作

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

17.1.1 Image类

Image类为源自 Bitmap 和 Metafile 的类提供功能的抽象基类。

Image的属性大多数是只读的:

  1. FrameDimensionsList:获取GUID的数组,这些GUID表示Image中帧的维数。
  2. Size:获取此图像的宽度和高度(单位:像素)。
  3. Width:获取Image的宽度(单位:像素)。
  4. Height:获取Image的高度(单位:像素)。
  5. HorizontalResolution:获取水平分辨率(单位:像素/英寸)。
  6. VerticalResolution:获取垂直分辨率(单位:像素/英寸)。
  7. PixelFormat:获取Image中每个像素的颜色数据的格式。
  8. PropertyIdList:获取存储于Image中的属性项的ID。
  9. PropertyItems:获取存储于Image中的所有属性项(元数据片)。
  10. RawFormat:获取Image的文件格式。

Image常用方法:

  1. Clone:创建此 Image 的一个精确副本。
  1. FromFile:从指定的文件创建Image。
  2. FromHbitmap:从GDI位图的句柄创建Bitmap。
  3. FromStream:从指定的数据流创建Image。
  4. FrameDimensionsList:获取GUID数组,这些GUID表示此Image中帧的维数。
  5. GetBounds:以指定的单位获取图像的界限。
  6. GetEncoderParameterList:返回有关指定的图像编码器所支持的参数的信息。
  7. GetFrameCount:返回指定维度的帧数。
  8. GetPropertyItem:获取指定的属性项。
  9. GetThumbnailImage:返回缩略图。
  10. IsAlphaPixelFormat:获取像素格式是否包含alpha信息。
  11. RemovePropertyItem:从Image移除指定的属性项。
  12. RotateFlip:旋转、翻转或者同时旋转和翻转Image。
  13. Save:保存到指定的文件或流。
  14. SaveAdd:在上一Save方法调用所指定的文件或流内添加一帧。
  15. SelectActiveFrame:选择由维度和索引指定的帧。
  16. SetPropertyItem:存储一个属性项。

由于Image类没有提供构造函数,只能通过FromFile、FromStream或者FromHbitmap方法来创建Image对象实例。

【例 17.1【项目:code17-001】获取图片信息。

        private void button1_Click(object sender, EventArgs e)

        {

            string imgfile;

            OpenFileDialog ofd =new OpenFileDialog();

            ofd.Filter = "图片文件|*.jpg;*.bmp;*.png;*.gif";

            if (ofd.ShowDialog() != DialogResult.OK)

                return;

            imgfile = ofd.FileName;

            //从图片文件创建Image实例

            Image img  = Image.FromFile(imgfile);

            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;

            pictureBox1.Image = img;

            textBox1.Text = "图片高度:" + img.Height + "\r\n";

            textBox1.Text += "图片宽度:" + img.Width + "\r\n";

            textBox1.Text += "图片水平分辨率:" + img.HorizontalResolution + "\r\n";

            textBox1.Text += "图片垂直分辨率:" + img.VerticalResolution + "\r\n";

            textBox1.Text += "文件格式:" + img.RawFormat.ToString() + "\r\n";

            textBox1.Text += "像素格式:" + img.PixelFormat.ToString() + "\r\n";

        }

运行结果如下图所示:

图17-1 获取图片信息

【例 17.2【项目:code17-002】翻转和旋转图片。

请在窗体上放置两个Button控件、一个ComboBox控件、一个PictureBox控件。

本例主要使用Image类的RotateFlip方法,它的参数是一个RotateFlipType枚举,包含以下成员:

  1. RotateNoneFlipNone:指定不进行旋转和翻转。
  2. RotateNoneFlipX:水平翻转。
  3. RotateNoneFlipY:垂直翻转。
  4. RotateNoneFlipXY:水平翻转和垂直翻转。
  5. Rotate90FlipNone: 90度顺时针旋转。
  6. Rotate90FlipX:水平翻转和90度顺时针旋转。
  7. Rotate90FlipY:垂直翻转和90度顺时针旋转。
  8. Rotate90FlipXY:水平翻转、垂直翻转和90度顺时针旋转。
  9. Rotate180FlipNone:180度顺时针旋转。
  10. Rotate180FlipX:水平翻转和180度顺时针旋转。
  11. Rotate180FlipY:垂直翻转和180度顺时针旋转。
  12. Rotate180FlipXY:水平翻转、垂直翻转和180度顺时针旋转。
  13. Rotate270FlipNone:270度顺时针旋转。
  14. Rotate270FlipX:水平翻转和270度顺时针旋转。
  15. Rotate270FlipY:垂直翻转和270度顺时针旋转。
  16. Rotate270FlipXY:水平翻转、垂直翻转和270度顺时针旋转。

请在ComboBox的Items属性中加入以上成员的名称。同时,为了观察图片变化,请将PictureBox控件的SizeMode 属性设置为AutoSize。具体代码如下:

        //窗体级变量,保存打开的图片

        Image sourceImg;

        //打开图片并显示在图片框内

        private void Button1_Click(object sender, EventArgs e)

        {

            string imgfile;

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Filter = "图片文件|*.jpg";

            if (ofd.ShowDialog() != DialogResult.OK)

                return;

            imgfile = ofd.FileName;

            //从图片文件创建Image实例

            sourceImg = Image.FromFile(imgfile);

            pictureBox1.Image = sourceImg;

        }

        private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)

        {

            if (pictureBox1.Image == null)

                return;

            Image destImg;

            //克隆图片

            destImg = (Image)sourceImg.Clone();

            //根据组合框文本,使用RotateFlip方法旋转图片

            switch( comboBox1.Text)

            {

                case "Rotate180FlipX":

                    destImg.RotateFlip(RotateFlipType.Rotate180FlipX);

                    break;

                case "Rotate180FlipNone":

                    destImg.RotateFlip(RotateFlipType.Rotate180FlipNone);

                    break;

                case "Rotate180FlipXY":

                    destImg.RotateFlip(RotateFlipType.Rotate180FlipXY);

                    break;

                case "Rotate180FlipY":

                    destImg.RotateFlip(RotateFlipType.Rotate180FlipY);

                    break;

                case "Rotate270FlipNone":

                    destImg.RotateFlip(RotateFlipType.Rotate270FlipNone);

                    break;

                case "Rotate270FlipX":

                    destImg.RotateFlip(RotateFlipType.Rotate270FlipX);

                    break;

                case "Rotate270FlipXY":

                    destImg.RotateFlip(RotateFlipType.Rotate270FlipXY);

                    break;

                case "Rotate90FlipNone":

                    destImg.RotateFlip(RotateFlipType.Rotate90FlipNone);

                    break;

                case "Rotate90FlipX":

                    destImg.RotateFlip(RotateFlipType.Rotate90FlipX);

                    break;

                case "Rotate90FlipXY":

                    destImg.RotateFlip(RotateFlipType.Rotate90FlipXY);

                    break;

                case "Rotate90FlipY":

                    destImg.RotateFlip(RotateFlipType.Rotate90FlipY);

                    break;

                case "RotateNoneFlipNone":

                    destImg.RotateFlip(RotateFlipType.RotateNoneFlipNone);

                    break;

                case "RotateNoneFlipX":

                    destImg.RotateFlip(RotateFlipType.RotateNoneFlipX);

                    break;

                case "RotateNoneFlipXY":

                    destImg.RotateFlip(RotateFlipType.RotateNoneFlipXY);

                    break;

                case "RotateNoneFlipY":

                    destImg.RotateFlip(RotateFlipType.RotateNoneFlipY);

                    break;

            }

            pictureBox1.Image = destImg;

        }

        //保存旋转后的图片

        private void Button2_Click(object sender, EventArgs e)

        {

            string imgfile;

            SaveFileDialog sfd = new SaveFileDialog();

            sfd.Filter = "图片文件|*.jpg";

            if (sfd.ShowDialog() != DialogResult.OK)

                return;

            imgfile = sfd.FileName;

            //Save方法保存图片

            pictureBox1.Image.Save(imgfile, System.Drawing.Imaging.ImageFormat.Jpeg);

        }

    }

运行结果如下图所示:

图17-2 图片的翻转和旋转

17.1.2 Bitmap类

Bitmap类常用于封装 GDI+ 位图、处理由像素数据定义的图像的对象。

由于Bitmap类继承于Image类,Image类的属性和方法都可以使用。

Bitmap特有方法:

  1. FromHicon:从图标的Windows句柄创建 Bitmap。
  2. FromResource:从指定的Windows资源创建 Bitmap。
  3. GetPixel:获取Bitmap中指定坐标位置像素的颜色。
  4. SetPixel:设置Bitmap中指定坐标位置像素的颜色。
  5. LockBits:将Bitmap锁定到系统内存中。
  6. UnlockBits:从系统内存解锁Bitmap。
  7. MakeTransparent:用默认或指定的颜色使Bitmap透明。

创建一个Bitmap实例,常采用以下方法:

1、使用Bitmap的构造函数。

Bitmap提供了12种构造函数,常用的是:

  1. Bitmap(String):从指定的文件初始化Bitmap类的新实例。例如:

Bitmap sourceImg = new Bitmap("c:\\lessons\\3.jpg");

  1. Bitmap(Int32, Int32):用指定的宽度和高度初始化Bitmap类的新实例。例如:

Bitmap sourceImg = new Bitmap(this.Width ,this.Height);

2、使用方法创建:

  1. FromFile(String):使用Image的方法从指定的文件创建Bitmap。例如:

Bitmap sourceImg = (Bitmap)Image.FromFile("c:\\lessons\\3.jpg");

  1. Clone:创建此 Bitmap的一个精确副本

Bitmap destImg = (Bitmap)sourceImg.Clone();

Bitmap类的操作和Image类类似,这里不再累述。

17.1.3 获得图片Exif信息

有些照片保存了拍摄时使用的的相机品牌、型号以及GPS、光圈、快门、白平衡、ISO、焦距、日期时间等信息,通常称为Exif(Exchangeable image file format)信息,保存在Jpg文件头部。

使用Image类或Bitmap类的PropertyItems属性很容易获得图片的Exif信息。

PropertyItems是一个PropertyItem类数组,这些对象分别对应于此图像中存储的每个属性项。

注意:PropertyItem类位于System.Drawing.Imaging命名空间。

PropertyItem有4个属性:

  1. Id:某个图像信息的ID。
  2. Value:某个图像信息的值。
  3. Len:Value属性的长度(以字节为单位)。
  4. Type:整数,它定义了Value 属性包含的数据类型。

使用PropertyItem需要注意以下事项:

1、不同的Id有着不同的含义,例如Id从0至26都是关于gps信息。还有些常见信息如下(Id使用的是十六进制表示):

  1. 010F:PropertyTagEquipMake,相机生产厂家。
  2. 0110:PropertyTagEquipModel,相机型号。
  1. 829A:PropertyTagExifExposureTim,快门速度。
  2. 829D:PropertyTagExifFNumber,光圈。
  3. 9000:PropertyTagExifVer,Exif版本。
  4. 9207:PropertyTagExifMeteringMod,曝光的测光方法。
  5. 920A:PropertyTagExifFocalLength,焦距。

更多Id及其相关说明可以参看:Property item descriptions - Win32 apps | Microsoft Learn

2、不同的Type对应不同的数据类型,但是还是需要根据具体的Id来处理数据。表17-1列出了Type值对应的主要的数据类型:

表17-1 Type说明

表示的类型

1

字节数组。

2

ASCII字符串,末尾以字符0结束。使用此类型时,对应的Len属性应设置为包括字符0的字符串长度。例如,字符串“Hello”的长度为6。

3

无符号的短(16位)整型数组。

4

无符号的长(32位)整型数组。

5

无符号的长整型对数组。

6

可以包含任何数据类型的值的字节数组。

7

有符号的长(32位)整型数组。

10

有符号的长整型对数组。

从表17-1可以看出,类型5和10是长整型对数组,每个长整型对的长度为8字节,前面用来表示分数,前4个字节是分子,后4个字节是分母。可以使用BitConverter 类将基础数据类型与字节数组相互转换,具体代码请参看【例 17.3】。

分数值具体用带“/”的分数表示还是小数值表示,应该参考日常摄影术语。例如

829A(快门速度)获得的值为1/60,表示为1/60;

829D(光圈)获得的值为45/10,表示为4.5;

920A(焦距)获得的值为33/5,表示为6.6。

3、即使Type值相同,处理数据的方式也可能不同。

例如Id为9000和Id为9101这两个图像信息,Type都是7,但是处理方式不相同:

9000(PropertyTagExifVer),获得的字节数组为:48,50,50,48,对应ASCII字符为:0220,也就是图片数据Exif版本为0220。

9101(PropertyTagExifCompConfig),获得的字节数组为:1,2,3,0。对应的数据就是1230,像素数据的顺序. 大多数情况下RGB格式使用4,5,6,0,而YCbCr 格式使用1,2,3,0。

【例 17.3【项目:code17-003】获取图片的Exif信息。

        private void button1_Click(object sender, EventArgs e)

        {

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Filter = "JPG文件|*.jpg";

            ofd.FileName = "";

            if (ofd.ShowDialog() != DialogResult.OK)

                return;

            string filename;

            filename = ofd.FileName;

            getPicInfo(filename);

        }

        //获得图片中的exif信息

        private void getPicInfo(string picFullPath)

        {

            listBox1.Items.Clear();

            Bitmap bmp =new Bitmap(picFullPath);

            string strPro = "";

            //不断枚举PropertyItems里面的内容

            foreach(System.Drawing.Imaging.PropertyItem pro in bmp.PropertyItems)

            {

                string strTmp;

                //根据类型进行大致处理,实际处理的时候应该根据具体的Id号进行处理

                switch( pro.Type)

                {

                        case 1:

                        strTmp = "length:" + pro.Len;

                        break;

                    case 2:

                        strTmp = System.Text.Encoding.ASCII.GetString(pro.Value).Replace("\0", "");

                        break;

                    case 3:

                        strTmp = BitConverter.ToInt16(pro.Value, 0).ToString();

                        break;

                    case 4:

                        strTmp = BitConverter.ToInt32(pro.Value, 0).ToString();

                        break;

                    case 5:

                        strTmp = getvalue(pro.Id, pro.Value).ToString();

                        break;

                    case 6:

                        strTmp = "type:" + pro.Type + " " + pro.Value.ToString();

                        break;

                    case 7:

                        strTmp = getascvalue(pro.Id, pro.Value);

                        break;

                    case 10:

                        strTmp = getvalue(pro.Id, pro.Value).ToString();

                        break;

                    default:

                    strTmp = "type:" + pro.Type + " " + pro.Value.ToString();

                        break;

                }

                //按照 Id-数据长度-数据类型-数据 显示

                listBox1.Items.Add(pro.Id.ToString("x").ToUpper() + "--" + pro.Len + "--" + pro.Type + "--" + strTmp);

            }

        }

       

        //处理整型对

        private string getvalue(int id, byte[] bteValue)

        {

            int intFirst;

            int intSecond;

            if (bteValue.Length == 8)

            {

                //将字节数组前4位转为Int32

                intFirst = BitConverter.ToInt32(bteValue, 0);

                //将字节数组后4为转为Int32

                intSecond = BitConverter.ToInt32(bteValue, 4);

                //如果是快门速度,那么返回分数,否则返回小数

                if (id == 33434)

                    return intFirst.ToString() + "/" + intSecond.ToString();

                return (intFirst / intSecond).ToString();

            }

            else

                //更多的数据不再处理

                return "0";

        }

        private string getascvalue(int id, byte[] bteValue)

        {

            if (bteValue.Length > 8)

                return ("length:" + bteValue.Length);

            if (id == 36864)

                return (Encoding.ASCII.GetString(bteValue));

            string returnString="";

            for (int i = 0;i< bteValue.Length; i++)

                returnString += bteValue[i].ToString() + " ";

            return returnString;

        }

运行结果如下图所示:

图17-3 图片的Exif信息

【例 17.4【项目:code17-004】获取图片的经纬度信息。

通常情况下,通过Gps信息的经纬度和海拔高度就可以对坐标位置定位。图片Exif信息中就包含相关的经纬度信息(根据具体拍照设备设置),对应的PropertyItem.Id是从0至26。比较关键的几个Id是:

  1. 1:纬度参照,指示纬度是北纬还是南纬。值为N表示北纬;值为S表示南纬。
  2. 2:纬度。
  3. 3:经度参照,指示经度是东经还是西经。值为E表示东经;值为W表示西经。
  4. 4:经度。
  5. 5:海拔参照。值为0,表示海平面上;值为1,表示海平面下。
  6. 6:海拔。

其中,纬度和经度的Type是5,长度为24的字节数组,其中前8个字节表示度,中间8个字节表示分,末尾8个字节表示秒。而每8个字节都是一个整数对。里面的前4字节表示分子,后4字节表示分母。

具体代码如下:

       private void button1_Click(object sender, EventArgs e)

        {

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Filter = "JPG文件|*.jpg";

            ofd.FileName = "";

            if (ofd.ShowDialog() != DialogResult.OK)

                return;

            string filename;

            filename = ofd.FileName;

            getPicGpsInfo(filename);

        }

       

        //获得图片的Gps信息

        private void getPicGpsInfo(string picFullPath)

        {

            listBox1.Items.Clear();

            Bitmap bmp =new Bitmap(picFullPath);

            string strPro = "";

   

            //纬度参照

            string PropertyTagGpsLatitudeRef = "";

            //纬度

            string PropertyTagGpsLatitude = "";

            //经度参照

            string PropertyTagGpsLongitudeRef = "";

            //经度

            string PropertyTagGpsLongitude = "";

            //海拔参照

            string PropertyTagGpsAltitudeRef = "";

            //海拔

            string PropertyTagGpsAltitude = "";

   

            foreach(System.Drawing.Imaging.PropertyItem pro in bmp.PropertyItems)

            {

                switch(pro.Id)

                {

                    case 1:

                        PropertyTagGpsLatitudeRef = System.Text.Encoding.ASCII.GetString(pro.Value).Replace("\0", "");

                        break;

                    case 2:

                        PropertyTagGpsLatitude = getGpsLL(pro.Value);

                        break;

                    case 3:

                        PropertyTagGpsLongitudeRef = System.Text.Encoding.ASCII.GetString(pro.Value).Replace("\0", "");

                        break;

                    case 4:

                            PropertyTagGpsLongitude = getGpsLL(pro.Value);

                        break;

                    case 5:

                            PropertyTagGpsAltitudeRef = pro.Value[0].ToString();

                        break;

                    case 6:

                        PropertyTagGpsAltitude = getGpsAltitude(pro.Value);

                        break;

                    default:

                        //其它值不处理

                        break;

                }

            }

            if (PropertyTagGpsLatitude != "")

            {

                switch (PropertyTagGpsLatitudeRef)

                {

                    case "":

                    case "N":

                        listBox1.Items.Add("纬度:北纬 " + PropertyTagGpsLatitude);

                        break;

                    default:

                        listBox1.Items.Add("纬度:南纬 " + PropertyTagGpsLatitude);

                        break;

                }

            }

            else

                listBox1.Items.Add("纬度:没有纬度位置");

            if (PropertyTagGpsLongitude != "")

            {

                switch (PropertyTagGpsLongitudeRef)

                {

                    case "":

                    case "E":

                        listBox1.Items.Add("经度:东经 " + PropertyTagGpsLongitude);

                        break;

                    default:

                        listBox1.Items.Add("经度:西经 " + PropertyTagGpsLongitude);

                        break;

                }

            }

            else

                listBox1.Items.Add("经度:没有经度位置");

            if (PropertyTagGpsAltitude != "")

            {

                switch (PropertyTagGpsAltitudeRef)

                {

                    case "":

                    case "0":

                        listBox1.Items.Add("海拔:" + PropertyTagGpsAltitude);

                        break;

                    default:

                        listBox1.Items.Add("海拔:-" + PropertyTagGpsAltitude);

                        break;

                }

            }

            else

                listBox1.Items.Add("海拔:没有海拔高度");

         }

         //获取纬度和经度的度分秒

        private string getGpsLL(byte[] bteValue)

        {

            if (bteValue.Length != 24)

                return "";

            string strTmp = "";

            int intFirst;

            int intSecond;

            //前8个字节是度

            intFirst = BitConverter.ToInt32(bteValue, 0);

            intSecond = BitConverter.ToInt32(bteValue, 4);

            strTmp += (intFirst / intSecond).ToString() + "°";

            //中间8个字节是分

            intFirst = BitConverter.ToInt32(bteValue, 8);

            intSecond = BitConverter.ToInt32(bteValue, 12);

            strTmp += (intFirst / intSecond).ToString() + "'";

            //末尾8个字节是秒

            intFirst = BitConverter.ToInt32(bteValue, 16);

            intSecond = BitConverter.ToInt32(bteValue, 20);

            strTmp += (intFirst / intSecond).ToString() + "\"";

           return strTmp;

       }

        //获取海拔

        private string getGpsAltitude(byte[] bteValue)

        {

            if (bteValue.Length != 8)

                return "";

            int intFirst;

            int intSecond;

            intFirst = BitConverter.ToInt32(bteValue, 0);

            intSecond = BitConverter.ToInt32(bteValue, 4);

            return (intFirst / intSecond).ToString() + "米";

        }

运行结果如下图所示:

图17-4 图片的Gps信息

学习更多vb.net知识,请参看vb.net 教程 目录

学习更多C#知识,请参看C#教程 目录

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962424.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实验七 JSP内置对象II

实验七 JSP内置对象II 目的&#xff1a; 1、掌握JSP内置对象的使用。 2、理解JSP的作用域 3、掌握session&#xff0c;application对象的使用 实验要求&#xff1a; 1、完成实验题目 2、要求提交实验报告&#xff0c;将代码和实验结果页面截图放入报告中 实验过程&#xff1a…

每日一博 - 三高系统架构设计:高性能、高并发、高可用性解析

文章目录 引言一、高性能篇1.1 高性能的核心意义 1.2 影响系统性能的因素1.3 高性能优化方法论1.3.1 读优化&#xff1a;缓存与数据库的结合1.3.2 写优化&#xff1a;异步化处理 1.4 高性能优化实践1.4.1 本地缓存 vs 分布式缓存1.4.2 数据库优化 二、高并发篇2.1 高并发的核心…

FFmpeg(7.1版本)的基本组成

1. 前言 FFmpeg 是一个非常流行的开源项目&#xff0c;它提供了处理音频、视频以及其他多媒体内容的强大工具。FFmpeg 包含了大量的库&#xff0c;可以用来解码、编码、转码、处理和播放几乎所有类型的多媒体文件。它广泛用于视频和音频的录制、转换、流媒体传输等领域。 2. F…

灵芝黄金基因组注释-文献精读109

The golden genome annotation of Ganoderma lingzhi reveals a more complex scenario of eukaryotic gene structure and transcription activity 灵芝&#xff08;Ganoderma lingzhi&#xff09;的黄金基因组注释揭示了更复杂的真核基因结构和转录活性情况 摘要 背景 普遍…

51单片机入门_01_单片机(MCU)概述(使用STC89C52芯片;使用到的硬件及课程安排)

文章目录 1. 什么是单片机1.1 微型计算机的组成1.2 微型计算机的应用形态1.3 单板微型计算机1.4 单片机(MCU)1.4.1 单片机内部结构1.4.2 单片机应用系统的组成 1.5 80C51单片机系列1.5.1 STC公司的51单片机1.5.1 STC公司单片机的命名规则 2. 单片机的特点及应用领域2.1 单片机的…

记忆化搜索(5题)

是什么&#xff1f; 是一个带备忘录的递归 如何实现记忆化搜索 1.添加一个备忘录&#xff08;建立一个可变参数和返回值的映射关系&#xff09; 2.递归每次返回的时候把结果放到备忘录里 3.在每次进入递归的时候往备忘录里面看看。 目录 1.斐波那契数列 2.不同路径 3.最…

Redis_Redission的入门案例、多主案例搭建、分布式锁进行加锁、解锁底层源码解析

目录 ①. Redis为什么选择单线程&#xff1f; ②. 既然单线程这么好,为什么逐渐又加入了多线程特性&#xff1f; ③. redis6的多线程和IO多路复用入门篇 ④. Redis6.0默认是否开启了多线程&#xff1f; ⑤. REDIS多线程引入总结 ①. Redis为什么选择单线程&#xff1f; ①…

本地运行大模型效果及配置展示

电脑上用ollama安装了qwen2.5:32b&#xff0c;deepseek-r1:32b&#xff0c;deepseek-r1:14b&#xff0c;llama3.1:8b四个模型&#xff0c;都是Q4_K_M量化版。 运行过程中主要是cpu和内存负载比较大&#xff0c;qwen2.5:32b大概需要22g&#xff0c;deepseek-r1&#xff1a;32b类…

新一代搜索引擎,是 ES 的15倍?

Manticore Search介绍 Manticore Search 是一个使用 C 开发的高性能搜索引擎&#xff0c;创建于 2017 年&#xff0c;其前身是 Sphinx Search 。Manticore Search 充分利用了 Sphinx&#xff0c;显着改进了它的功能&#xff0c;修复了数百个错误&#xff0c;几乎完全重写了代码…

从0开始,来看看怎么去linux排查Java程序故障

一&#xff0c;前提准备 最基本前提&#xff1a;你需要有liunx环境&#xff0c;如果没有请参考其它文献在自己得到local建立一个虚拟机去进行测试。 有了虚拟机之后&#xff0c;你还需要安装jdk和配置环境变量 1. 安装JDK&#xff08;以OpenJDK 17为例&#xff09; 下载JDK…

MFC开发,给对话框添加垂直滚动条并解决鼠标滚动响应的问题

无论在使用QT或者MFC进行界面开发时&#xff0c;都会出现在一个对话框里面存在好多的选项&#xff0c;导致对话框变得非常长或者非常大&#xff0c;就会显现的不美观&#xff0c;在这种情况下通常是添加一个页面的滚动条来解决这个问题&#xff0c;下面我们就来介绍给MFC的对话…

(二)QT——按钮小程序

目录 前言 按钮小程序 1、步骤 2、代码示例 3、多个按钮 ①信号与槽的一对一 ②多对一&#xff08;多个信号连接到同一个槽&#xff09; ③一对多&#xff08;一个信号连接到多个槽&#xff09; 结论 前言 按钮小程序 Qt 按钮程序通常包含 三个核心文件&#xff1a; m…

QT简单实现验证码(字符)

0&#xff09; 运行结果 1&#xff09; 生成随机字符串 Qt主要通过QRandomGenerator类来生成随机数。在此之前的版本中&#xff0c;qrand()函数也常被使用&#xff0c;但从Qt 5.10起&#xff0c;推荐使用更现代化的QRandomGenerator类。 在头文件添加void generateRandomNumb…

受击反馈HitReact、死亡效果Death Dissolve、Floating伤害值Text(末尾附 客户端RPC )

受击反馈HitReact 设置角色受击标签 (GameplayTag基本了解待补充) 角色监听标签并设置移动速度 创建一个受击技能&#xff0c;并应用GE 实现设置角色的受击蒙太奇动画 实现角色受击时播放蒙太奇动画&#xff0c;为了保证通用性&#xff0c;将其设置为一个函数&#xff0c;并…

C++,STL 命名空间:理解 std 的作用、规范与陷阱

文章目录 引言一、为什么需要 std 命名空间&#xff1f;二、std 命名空间的组成三、使用 std 命名空间的正确姿势1. 显式作用域限定2. 谨慎使用 using 声明3. 头文件中禁止 using namespace std 四、常见陷阱与解决方案陷阱 1&#xff1a;与第三方库命名冲突陷阱 2&#xff1a;…

第11章:根据 ShuffleNet V2 迁移学习医学图像分类任务:甲状腺结节检测

目录 1. Shufflenet V2 2. 甲状腺结节检测 2.1 数据集 2.2 训练参数 2.3 训练结果 2.4 可视化网页推理 3. 下载 1. Shufflenet V2 shufflenet v2 论文中提出衡量轻量级网络的性能不能仅仅依靠FLOPs计算量&#xff0c;还应该多方面的考虑&#xff0c;例如MAC(memory acc…

【ArcGIS遇上Python】批量提取多波段影像至单个波段

本案例基于ArcGIS python,将landsat影像的7个波段影像数据,批量提取至单个波段。 相关阅读:【ArcGIS微课1000例】0141:提取多波段影像中的单个波段 文章目录 一、数据准备二、效果比对二、python批处理1. 编写python代码2. 运行代码一、数据准备 实验数据及完整的python位…

HTB:Administrator[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用nmap对靶机…

vscode+WSL2(ubuntu22.04)+pytorch+conda+cuda+cudnn安装系列

最近在家过年闲的没事&#xff0c;于是研究起深度学习开发工具链的配置和安装&#xff0c;之前欲与天公试比高&#xff0c;尝试在win上用vscodecuda11.6vs2019的cl编译器搭建cuda c编程环境&#xff0c;最后惨败&#xff0c;沦为笑柄&#xff0c;痛定思痛&#xff0c;这次直接和…

亚博microros小车-原生ubuntu支持系列:17 gmapping

前置依赖 先看下亚博官网的介绍 Gmapping简介 gmapping只适用于单帧二维激光点数小于1440的点&#xff0c;如果单帧激光点数大于1440&#xff0c;那么就会出【[mapping-4] process has died】 这样的问题。 Gmapping是基于滤波SLAM框架的常用开源SLAM算法。 Gmapping基于RBp…