美文网首页
C#图像处理之截取panel

C#图像处理之截取panel

作者: 流量地球 | 来源:发表于2020-07-07 18:18 被阅读0次

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System;

using System.Configuration;

using System.IO;

using System.Xml;

using System.Data.SqlClient;

using System.Data.OleDb;

using System.Net.NetworkInformation;

using System.Diagnostics;

using System.Reflection;

using Microsoft.Win32;

using System.Text.RegularExpressions;

using System.Threading;

using System.Net;

using System.Runtime.InteropServices;

namespace W

{

    public partial class Form1 : Form

    {

        #region 初始化

        public Form1()

        {

            InitializeComponent();

        }

        public static int cvt_int(object num)

        {

            try { return (int)Convert.ToDouble(num); }

            catch { return 0; }

        }

        #endregion

        #region 截图

        private void button2_Click(object sender, EventArgs e)

        {

            Camera.WVS_ForceSendLaneHv(1,0);

        }

        private void textBox3_TextChanged(object sender, EventArgs e)

        {

            try{

                Convert.ToInt32(textBox3.Text);

            }

            catch{

            textBox3.Text="0";

            }

        }

        private void label10_Click(object sender, EventArgs e)

        {

        }

        bool enDraw = false;

        private void catchPicBTN_Click(object sender, EventArgs e)

        {//  Create  pen. 

          // takePicPlus(videoPanel);

        ////2、正方形

        //g.DrawRectangle(thepen, ps.X, ps.Y, 0.5F, 0.5F);

        ////3、指定的图形

        //Bitmap  bm=new  Bitmap(2,2);    //这里调整点的大小 

        //bm.SetPixel(0,  0,  color);      //设置点的颜色 

        //bm.SetPixel(0,  1,  color); 

        //bm.SetPixel(1,  0,  color); 

        //bm.SetPixel(1,  1,  color); 

        //Graphics  g  =  Graphics.FromHwnd(this.panel1.Handle);    //画在哪里   

        //g.DrawImageUnscaled(bm,  e.X,  e.Y);      //具体坐标

            //Form1_Paint(this, new PaintEventArgs(CreateGraphics(), ClientRectangle));

            if(catchPicBTN.Text.Equals("绘制识别区域"))

            {

                enDraw = true;

                catchPicBTN.Text="开启软件抓拍";

            }

            else if(catchPicBTN.Text.Equals("开启软件抓拍")&&pointYList.Count>=4)

            {

                enDraw =false;

                catchPicBTN.Text="关闭软件抓拍";

                //获取最大四边形区域

                getMaxPlace();

                // takePic4Math(videoPanel).Save(picPath());

                //开启区域内抓拍线程

                //takePicSharp();

                ImageHashHelper.getMathPoint(pointXList, pointYList);

                timer4catchPicTick = true;

                //catchPicThread = new Thread(catchPic);

                //catchPicThread.IsBackground = true;

                //catchPicThread.Start();

            }else if(catchPicBTN.Text.Equals("关闭软件抓拍"))

            {

                //catchPicThread.Join();

                //关闭区域内抓拍线程

                //清除最大四边形区域

                  catchPicBTN.Text="绘制识别区域";

                  clearVideoPanelPaint(videoPanel.CreateGraphics());

            }

            //整个Panel上截图

            //takePic(videoPanel).Save(picPath());

        }

        void takePicPlus(Panel panel) // Bitmap takePicPlus(Panel panel)

        {

            Bitmap bitmap = new Bitmap(128, 160);

            //创建作图区域 

            Graphics graphic = Graphics.FromImage(bitmap);

                Point p = panel.PointToScreen(panel.Location);

                //截取原图相应区域写入作图区 

                //graphic.DrawImage(this.pb_photo_original.Image, new Rectangle(0, 0, 128, 160), oldCutRect, GraphicsUnit.Pixel);

                graphic.CopyFromScreen(p.X, p.Y, 0, 0, new Size(128, 160));

                Bitmap zoomBitmap = new Bitmap(bitmap, new Size(80, 100));

                //panel.Image = zoomBitmap;

                //保存图象 

                zoomBitmap.Save(@"D:\test.jpg");

                //return bitmap;

            bitmap.Dispose();

            graphic.Dispose(); 

        }

        void takePicPP(Panel panel) // Bitmap takePicPlus(Panel panel)

        {

            //Bitmap bitmap = new Bitmap(maxX - minX, maxY - minY);

            Bitmap bitmap = new Bitmap(maxX , maxY);

            //创建作图区域 

            Graphics graphic = Graphics.FromImage(bitmap);

            Point p = panel.PointToScreen(panel.Location);

            //截取原图相应区域写入作图区 

            graphic.DrawImage(bitmap, new Rectangle(0, 0, maxX, maxY));

            //graphic.CopyFromScreen(0, 0, p.X - minX, p.Y - minY, new Size(maxX - minX, maxY - minY));

            int tx=maxX - minX;

            int ty = maxY - minY;

            //Bitmap zoomBitmap = new Bitmap(bitmap, new Size(maxX - minX, maxY - minY));

            //panel.Image = zoomBitmap;

            //保存图象 

            //zoomBitmap.Save(@"D:\test.jpg");

            //return bitmap;

            bitmap.Save(@"D:\test1.jpg");

            bitmap.Dispose();

            graphic.Dispose();

        }

        Bitmap takePicSharp()

        {

            Bitmap bit = new Bitmap(maxX - minX, maxY - minY);

            //Bitmap bit = new Bitmap(videoPanel.Width, videoPanel.Height);

            Graphics g = Graphics.FromImage(bit);

            ///Point p = videoPanel.PointToScreen(videoPanel.Location);

            try

            {

                //stem.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);

                //g.CopyFromScreen(new Point(0, 0), new Point(0, 0), bit.Size);

                //g.CopyFromScreen(new Point(videoPanel.Location.X, videoPanel.Location.Y), new Point(videoPanel.Location.X, videoPanel.Location.Y), bit.Size);

              // g.CopyFromScreen(this.Location, Point.Empty, bit.Size);

                //1,2参数,截取的起始点,3,4绘制的的起始点,5图片大小

                g.CopyFromScreen(this.Location.X + (videoPanel.Location.X) + minX, this.Location.Y + (videoPanel.Location.Y) + minY, 0, 0, bit.Size);//videoPanel.Location.X +

                //SaveFileDialog saveFileDialog = new SaveFileDialog();

                //saveFileDialog.Filter = "bmp|*.bmp|jpg|*.jpg|gif|*.gif";

                //if (saveFileDialog.ShowDialog() != DialogResult.Cancel)

                //{

                //bit.Save(saveFileDialog.FileName);

                //}

                return bit;

            }

            finally {

                g.Dispose();

            }

        }

        Bitmap takePicSharpAll()

        {

            Bitmap bit = new Bitmap(videoPanel.Width, videoPanel.Height);

            //Bitmap bit = new Bitmap(videoPanel.Width, videoPanel.Height);

            Graphics g = Graphics.FromImage(bit);

            ///Point p = videoPanel.PointToScreen(videoPanel.Location);

            try

            {

                //stem.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);

                g.CopyFromScreen(this.Location, Point.Empty, bit.Size);

                //g.CopyFromScreen(new Point(videoPanel.Location.X, videoPanel.Location.Y), new Point(videoPanel.Location.X, videoPanel.Location.Y), bit.Size);

                // g.CopyFromScreen(this.Location, Point.Empty, bit.Size);

                //1,2参数,截取的起始点,3,4绘制的的起始点,5图片大小

                //g.CopyFromScreen(this.Location.X + (videoPanel.Location.X) + minX, this.Location.Y + (videoPanel.Location.Y) + minY, 0, 0, bit.Size);//videoPanel.Location.X +

                //SaveFileDialog saveFileDialog = new SaveFileDialog();

                //saveFileDialog.Filter = "bmp|*.bmp|jpg|*.jpg|gif|*.gif";

                //if (saveFileDialog.ShowDialog() != DialogResult.Cancel)

                //{

                //bit.Save(saveFileDialog.FileName);

                //}

                return bit;

            }

            finally

            {

                g.Dispose();

            }

        }

        //截取指定panel的图片

        Bitmap takePic(Panel panel)

        {

            Point ScrollMaxInfo = GetScrollPoint(panel);

            Size ControlMaxSize = GetControlSize(panel, ScrollMaxInfo);

            Bitmap TempImage = new Bitmap(panel.Width - 16, panel.Height - 16);

            Bitmap ControlImage = new Bitmap(ControlMaxSize.Width, ControlMaxSize.Height);

            Graphics MainGraphics = Graphics.FromImage(ControlImage);

            try

            {

                int StepWidth = GetScrollNumb(panel.Width - 16, ScrollMaxInfo.X);

                int StepHeight = GetScrollNumb(panel.Height - 16, ScrollMaxInfo.Y);

                int LogWidth = 0;

                int LogHeigh = 0;

                for (int i = 0; i != StepWidth; i++)

                {

                    LogHeigh = 0;

                    for (int z = 0; z != StepHeight; z++)

                    {

                        panel.DrawToBitmap(TempImage, new Rectangle(0, 0, panel.Width - 16, panel.Height - 16));

                        MainGraphics.DrawImage(TempImage, LogWidth, LogHeigh);

                        LogHeigh = GetScrollPoint(1, panel);

                    }

                    LogWidth = GetScrollPoint(0, panel);

                }

                return ControlImage;

            }

            finally{

                MainGraphics.Dispose();

                TempImage.Dispose();

            }

        }

        //截取指定panel的图片 4Math

        Bitmap takePic4Math(Panel panel)

        {

            Point ScrollMaxInfo = GetScrollPoint(panel);

            //Size ControlMaxSize = GetControlSize(panel, ScrollMaxInfo);

            Bitmap TempImage = new Bitmap(maxX - minX, maxY - minY);

            Bitmap ControlImage = new Bitmap(maxX - minX, maxY - minY);

            Graphics MainGraphics = Graphics.FromImage(ControlImage);

            try

            {

                int m = maxX - minX;

                int k = maxY - minY;

                int StepWidth = GetScrollNumb(maxX - minX, ScrollMaxInfo.X);

                int StepHeight = GetScrollNumb(maxY - minY, ScrollMaxInfo.Y);

                int LogWidth = 0;

                int LogHeigh = 0;

                for (int i = 0; i != StepWidth; i++)

                {

                    LogHeigh = 0;

                    for (int z = 0; z != StepHeight; z++)

                    {

                        panel.DrawToBitmap(TempImage, new Rectangle(minX, minY, maxX, maxY));

                        MainGraphics.DrawImage(TempImage, LogWidth, LogHeigh);

                        LogHeigh = GetScrollPoint(1, panel);

                    }

                    LogWidth = GetScrollPoint(0, panel);

                }

                return ControlImage;

            }

            finally

            {

                MainGraphics.Dispose();

                TempImage.Dispose();

            }

        }

        private string areaPicPath()

        {

            string picDir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "areaPic\\" + DateTime.Now.ToString("yyyy-MM-dd") + "\\";

            if (!Directory.Exists(picDir))

            {

                Directory.CreateDirectory(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "areaPic\\" + DateTime.Now.ToString("yyyy-MM-dd") + "\\");

            }

            string path = picDir + DateTime.Now.ToString("yyyyMMdd hhmmssfff") + ".png";

            return path;

        }

        private string picPath()

        {

            string picDir=System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase +"pic\\"+DateTime.Now.ToString( "yyyy-MM-dd")+"\\";

            if (!Directory.Exists(picDir))

            {

                Directory.CreateDirectory(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase +"pic\\"+DateTime.Now.ToString( "yyyy-MM-dd")+"\\");

            }

            string path = picDir + DateTime.Now.ToString("yyyyMMdd hhmmssfff") + ".png";

            return path;

        }

        #region API

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]

        public struct SCROLLINFO

        {

            public uint cbSize;

            public uint fMask;

            public int nMin;

            public int nMax;

            public uint nPage;

            public int nPos;

            public int nTrackPos;

        }

        public enum ScrollBarInfoFlags

        {

            SIF_RANGE = 0x0001,

            SIF_PAGE = 0x0002,

            SIF_POS = 0x0004,

            SIF_DISABLENOSCROLL = 0x0008,

            SIF_TRACKPOS = 0x0010,

            SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)

        }

        public enum ScrollBarRequests

        {

            SB_LINEUP = 0,

            SB_LINELEFT = 0,

            SB_LINEDOWN = 1,

            SB_LINERIGHT = 1,

            SB_PAGEUP = 2,

            SB_PAGELEFT = 2,

            SB_PAGEDOWN = 3,

            SB_PAGERIGHT = 3,

            SB_THUMBPOSITION = 4,

            SB_THUMBTRACK = 5,

            SB_TOP = 6,

            SB_LEFT = 6,

            SB_BOTTOM = 7,

            SB_RIGHT = 7,

            SB_ENDSCROLL = 8

        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]

        public static extern int GetScrollInfo(IntPtr hwnd, int bar, ref SCROLLINFO si);

        [DllImport("user32")]

        public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool Rush);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]

        public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

        #endregion

        /// <summary>

        /// 获取目前滚动条位置

        /// </summary>

        /// <param name="Bar"></param>

        /// <param name="MyControl"></param>

        /// <returns></returns>

        public static int GetScrollPoint(int Bar, Control MyControl)

        {

            SCROLLINFO ScrollInfo = new SCROLLINFO();

            ScrollInfo.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(ScrollInfo);

            ScrollInfo.fMask = (uint)ScrollBarInfoFlags.SIF_ALL;

            GetScrollInfo(MyControl.Handle, Bar, ref ScrollInfo);

            return ScrollInfo.nPos;

        }

        /// <summary>

        /// 获取循环几次获得图形

        /// </summary>

        /// <returns></returns>

        private static int GetScrollNumb(int MyControlNumb, int ScrollMaxInfoNumb)

        {

            double Step = (double)ScrollMaxInfoNumb / (double)MyControlNumb;

            Step++;

            if ((int)Step == Step)

            {

                return (int)Step;

            }

            else

            {

                return (int)Step + 1;

            }

        }

        /// <summary>

        /// 获得控件不需要滚动条的宽和高(最终图形大小)

        /// </summary>

        /// <param name="MyControl"></param>

        /// <param name="ScrollMaxInfo"></param>

        /// <returns></returns>

        private static Size GetControlSize(Control MyControl, Point ScrollMaxInfo)

        {

            return new Size(MyControl.Size.Width + ScrollMaxInfo.X - 16, MyControl.Size.Height + ScrollMaxInfo.Y - 16);

        }

        /// <summary>

        /// 获取滚动条数据

        /// </summary>

        /// <param name="MyControl"></param>

        /// <param name="ScrollSize"></param>

        /// <returns></returns>

        private static Point GetScrollPoint(Control MyControl)

        {

            Point MaxScroll = new Point();

            SCROLLINFO ScrollInfo = new SCROLLINFO();

            ScrollInfo.cbSize = (uint)System.Runtime.InteropServices.Marshal.SizeOf(ScrollInfo);

            ScrollInfo.fMask = (uint)ScrollBarInfoFlags.SIF_ALL;

            GetScrollInfo(MyControl.Handle, 1, ref ScrollInfo);

            MaxScroll.Y = ScrollInfo.nMax - (int)ScrollInfo.nPage;

            if ((int)ScrollInfo.nPage == 0) MaxScroll.Y = 0;

            GetScrollInfo(MyControl.Handle, 0, ref ScrollInfo);

            MaxScroll.X = ScrollInfo.nMax - (int)ScrollInfo.nPage;

            if ((int)ScrollInfo.nPage == 0) MaxScroll.X = 0;

            return MaxScroll;

        }

        #endregion 截图

        #region 绘图

        private void Form1_Paint(object sender, PaintEventArgs e)

        {

        }

        List<int> pointXList = new List<int>();

        List<int> pointYList = new List<int>();

        //private void videoPanel_Paint(object sender, PaintEventArgs e)

        //{

        //    Pen blackPen = new Pen(Color.Blue, 3);

        //    //  Create  coordinates  of  points  that  define  line. 

        //    int x1 = backx;

        //    int y1 = backy;

        //    int x2 = e.ClipRectangle.X;

        //    int y2 = e.ClipRectangle.Y;

        //    //  Draw  line  to  screen. 

        //    e.Graphics.DrawLine(blackPen, x1, y1, x2, y2);

        //    backx = x2;

        //    backy = y2;

        //}

        private void clearVideoPanelPaint(Graphics r)

        {

            if (!enDraw)

            {

                r.Clear(Color.Black);

                pointXList.Clear();

                pointYList.Clear();

                return;

            }

        }

        private void videoPanelPaint(object sender, MouseEventArgs e, Graphics r)

        {

            if (!enDraw)

            {

                r.Clear(Color.Black);

                pointXList.Clear();

                pointYList.Clear();

                return;

            }

            if (pointXList.Count >= 4)

            {

                pointXList.Add(pointXList[0]);

                pointYList.Add(pointYList[0]);

            }

            else

            {

                pointXList.Add(e.X);

                pointYList.Add(e.Y);

            }

            //if (e.Y == backy && backx == x1) return;

            //if (pointXList.Count >= 4) {

            //    x2 = pointXList[pointXList.Count - 1];

            //    y2 = pointYList[pointYList.Count - 1];

            //}

            try

            {

                Pen bluePen = new Pen(Color.Blue, 2);

                if (pointYList.Count == 1)

                {

                    r.DrawEllipse(bluePen, pointXList[0]-1, pointYList[0]-1,3,3);

                }

                //if (backy == 0 && backx == 0) return;

                else if(pointYList.Count>=2)

                {

                    //  Create  coordinates  of  points  that  define  line. 

                    //  Draw  line  to  screen. 

                    r.DrawLine(bluePen, pointXList[pointYList.Count - 1], pointYList[pointYList.Count - 1], pointXList[pointYList.Count - 2], pointYList[pointYList.Count - 2]);

                }

            }

            finally {

                if (pointXList.Count >= 5)

                {

                    if (ImageHashHelper.isInTriangle2(pointXList[0], pointYList[0], pointXList[1], pointYList[1], pointXList[2], pointYList[2], pointXList[3], pointYList[3]))

                    {

                        pointXList.Clear();

                        pointYList.Clear();

                        r.Clear(Color.Black);

                        textBox1.Text = "不要绘制凹四边形";

                    }

                    else

                    {

                        pointXList.RemoveAt(0);

                        pointYList.RemoveAt(0);

                    }

                }

            }

        }

        private void videoPanel_MouseDoubleClick(object sender, MouseEventArgs e)

        {

            videoPanelPaint(sender, e, videoPanel.CreateGraphics());

        }

        ////假设panel1是将直线盖住的控件

        //private void Form1_Paint(object sender, PaintEventArgs e)

        //{

        //e.Graphics.Clear(BackColor);

        //videoPanel.CreateGraphics().Clear(videoPanel.BackColor);

        //e.Graphics.DrawLine(Pens.Blue, new Point(0, 0), new Point(ClientRectangle.Width, ClientRectangle.Height));

        ////注意坐标系变换。

        //videoPanel.CreateGraphics().DrawLine(Pens.Black, new Point(-videoPanel.Left, -videoPanel.Top), new Point(ClientRectangle.Width - videoPanel.Left, ClientRectangle.Height - videoPanel.Top));

        //}

        //private void Form1_SizeChanged(object sender, EventArgs e)

        //{

        //Form1_Paint(this, new PaintEventArgs(CreateGraphics(), ClientRectangle));

        //}

        #endregion 绘图

        #region 识别区域

        int maxY;

        int maxX;

        int minX;

        int minY;

        void getMaxPlace()

        {

            if(pointYList.Count>=4&&pointXList.Count>=4)

            {

                maxY=pointYList[0];

                maxX=pointXList[0];

                minX=pointXList[0];

                minY=pointYList[0];

                foreach (int i in pointXList)

                {

                    if(i>maxX)

                    {

                        maxX=i;

                    }

                    if(i<minX)

                    {

                        minX=i;

                    }

                }

                foreach (int j in pointYList)

                {

                    if (j > maxY)

                    {

                        maxY = j;

                    }

                    if (j < minY)

                    {

                        minY = j;

                    }

                }

            }

            Graphics r = videoPanel.CreateGraphics();

            Pen redPen = new Pen(Color.Red, 2);

            r.DrawLine(redPen, minX, minY, maxX, minY);

            r.DrawLine(redPen, maxX, maxY, maxX, minY);

            r.DrawLine(redPen, maxX, maxY, minX, maxY);

            r.DrawLine(redPen, minX, minY, minX, maxY);

        }

        #endregion 识别区域

        #region 抓拍线程

        //Thread catchPicThread = null;

        void catchPic()

        {

            while (true) {

            }

        }

        #endregion 抓拍线程

        Bitmap pic4math = null;

        int loopSum = 0;

        double currentScore = 0;

        double scoreAvg = 0;

        bool initFlag = false;

        bool timer4catchPicTick = false;

        private void timer4catchPic_Tick(object sender, EventArgs e)

        {

            if (!timer4catchPicTick)

            {

                loopSum = 0;

                currentScore = 0;

                scoreAvg = 0;

                initFlag = false;

                timer4catchPicTick = false;

                return;

            }

            if (loopSum > 32)

            {

                initFlag = true;

            }

            if (loopSum > 1024)

            {

                loopSum = 0;

            }

            else

            {

                loopSum++;

            }

            pic4math = takePicSharp();

            //保存计算图片,到指定目录

          // pic4math.Save(areaPicPath());

            currentScore = (double)ImageHashHelper.getAvg4UserInArea(pic4math);

            if (initFlag)

            {

                if (currentScore > scoreAvg * 1.5 || currentScore * 1.66 < scoreAvg)

                {

                    takePicSharpAll().Save(picPath());

                    pic4math.Save(areaPicPath());

                    scoreAvg = scoreAvg + (currentScore - scoreAvg) / 32;

                }

                else

                {

                    scoreAvg = scoreAvg + (currentScore - scoreAvg) / 32;

                }

            }

            else

            {

                scoreAvg += currentScore / 32;

            }

            Thread.Sleep(64);

        }

    }

}

相关文章

  • C#图像处理之截取panel

    using System.Collections.Generic; using System.ComponentM...

  • C# 控制多个panel的方法

    C# 很多时候需要用到panel 面板来处理同一窗体,切换界面的问题 1.tabControl 优势: 即便在VS...

  • Win7 C#(vs2013)+EmguCV 3.2 调用本地摄

    OpenCV是由C/C++编写的图像处理库,C#不能直接调用, 但是EmguCV是使用C#对openCV进行封装。...

  • C#图像处理——ImageProcessor

    这是个老生常谈的话题,需求实在太多,而且也较简单,写此文也是因为几个月没写技术文章了,权当为下一步开个头。我之前也...

  • 明景视频图像处理分析系统

    专业视频图像处理分析系统是国家要求公安系统必须配备的一种视频侦查装备,具有视频图像增强、比对、截取、转换、检索等视...

  • 明景视频图像处理分析系统

    专业视频图像处理分析系统是国家要求公安系统必须配备的一种视频侦查装备,具有视频图像增强、比对、截取、转换、检索等视...

  • Android录屏和截屏命令

    视频录制和图像截取 视频录制和图像截取需要root权限后进入shell模式,使用 adb shell 命令即可进入...

  • Java截取视频图像

    java中对视频流的处理不是很方便,如果想截取视频中的图像,通常是通过ffmpeg.exe进行处理,然后再去获取结...

  • DXGI截取桌面图像

    DXGI截取桌面图像 使用DXGI截取桌面图像效率高,cpu占用低,是抓取桌面图像的好方法(只支持win8及以上)...

  • Panel圆角处理

    如果要设置圆角的控件不需要动态设置尺寸,可以直接复写OnResize(), 如下: 如果控件是动态设置尺寸的,就在...

网友评论

      本文标题:C#图像处理之截取panel

      本文链接:https://www.haomeiwen.com/subject/vtezqktx.html