当前位置: 首页 > news >正文

Halcon案例(二):C#联合Halcon回形针以及方向

  • 本案例分3部分
    1. 识别效果,分别显示识别前后识别后;
    2. 代码展示,分别是Halcon源码和Halcon转为C#的代码
    3. 代码解释(解释在源码中);
  • 原图如下

识别后图像:
其中计算回形针与X轴之间的夹角

Halcon代码:

* clip.hdev: Orientation of clips
*识别图像中的回形针,并且计算回形针与X轴之间的夹角
* 
*打开一张图像
read_image (Clip, 'clip')*获取图像大小
get_image_size (Clip, Width, Height)*关闭已经打开的窗口
dev_close_window ()*打开新窗口
dev_open_window (0, 0, Width / 2, Height / 2, 'black', WindowID)*在新窗口里显示图像
dev_display (Clip)*设置窗口字体显示,字体大小,字体样式,粗体,斜体
set_display_font (WindowID, 14, 'mono', 'true', 'false')*在窗口右下方显示"Press Run  (F5) to  continue"字样
*disp_continue_message (WindowID, 'black', 'true')*停止程序的执行
*stop ()*二值化操作
binary_threshold (Clip, Dark, 'max_separability', 'dark', UsedThreshold)*将区域进行连通处理
connection (Dark, Single)*过滤出面积大小在【5000, 10000】范围里的区域
select_shape (Single, Selected, 'area', 'and', 5000, 10000)*设置区域的填充方式
dev_set_draw ('fill')*设置输出显示对象的颜色数目
dev_set_colored (12)*在窗口右下方显示"Press Run  (F5) to  continue"字样
*disp_continue_message (WindowID, 'black', 'true')*停止程序的执行
*stop ()*显示图像
dev_display (Clip)*设置输出对象的颜色为绿色
dev_set_color ('yellow')*显示过滤后的区域
dev_display (Selected)*获取过滤后区域的方向
orientation_region (Selected, Phi)*获取过滤后区域的面积,中心的行坐标,列坐标
area_center (Selected, Area, Row, Column)*设置输出对象的线宽为3
dev_set_line_width (3)*设置区域的填充方式
dev_set_draw ('margin')
Length := 80*设置输出对象的颜色为蓝色
dev_set_color ('orange red')*在窗口上显示十字
disp_arrow (WindowID, Row, Column, Row - Length * sin(Phi), Column + Length * cos(Phi), 4)*在窗口上显示回形针的角度 将弧度转为角度deg(Phi)
disp_message (WindowID, deg(Phi)$'3.1f' + ' deg', 'image', Row, Column - 100, 'black', 'false')

C#代码:

#region 识别回形针方向
/// <summary>
/// 识别图像中的回形针,并且计算回形针与X轴之间的夹角
/// </summary>
public void RecognizeClipDirection(HTuple winId, string imagePath)
{HObject ho_Clip, ho_Dark, ho_Single, ho_Selected;// Local control variables HTuple hv_Width = new HTuple(), hv_Height = new HTuple();HTuple hv_UsedThreshold = new HTuple();HTuple hv_Phi = new HTuple(), hv_Area = new HTuple(), hv_Row = new HTuple();HTuple hv_Column = new HTuple(), hv_Length = new HTuple();// Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Clip);HOperatorSet.GenEmptyObj(out ho_Dark);HOperatorSet.GenEmptyObj(out ho_Single);HOperatorSet.GenEmptyObj(out ho_Selected);try{//clip.hdev: Orientation of clips//打开一张图像ho_Clip.Dispose();HOperatorSet.ReadImage(out ho_Clip, imagePath);//获取图像大小//hv_Width.Dispose();//hv_Height.Dispose();//HOperatorSet.GetImageSize(ho_Clip, out hv_Width, out hv_Height);//打开新窗口//HOperatorSet.SetWindowAttr("background_color", "black");//HOperatorSet.OpenWindow(0, 0, hv_Width / 2, hv_Height / 2, 0, "visible", "", out winId);//HDevWindowStack.Push(winId);//在新窗口里显示图像HOperatorSet.DispObj(ho_Clip, winId);//设置窗口字体显示,字体大小,字体样式,粗体,斜体Set_display_font(winId, 14, "mono", "true", "false");//二值化操作ho_Dark.Dispose();hv_UsedThreshold.Dispose();HOperatorSet.BinaryThreshold(ho_Clip, out ho_Dark, "max_separability", "dark", out hv_UsedThreshold);//将区域进行连通处理ho_Single.Dispose();HOperatorSet.Connection(ho_Dark, out ho_Single);//过滤出面积大小在【5000, 10000】范围里的区域ho_Selected.Dispose();HOperatorSet.SelectShape(ho_Single, out ho_Selected, "area", "and", 5000, 10000);//设置区域的填充方式HOperatorSet.SetDraw(winId, "fill");//设置输出显示对象的颜色数目HOperatorSet.SetColored(winId, 12);//显示图像HOperatorSet.DispObj(ho_Clip, winId);//设置输出对象的颜色为绿色HOperatorSet.SetColor(winId, "yellow");//显示过滤后的区域HOperatorSet.DispObj(ho_Selected, winId);//获取过滤后区域的方向hv_Phi.Dispose();HOperatorSet.OrientationRegion(ho_Selected, out hv_Phi);//获取过滤后区域的面积,中心的行坐标,列坐标hv_Area.Dispose();hv_Row.Dispose();hv_Column.Dispose();HOperatorSet.AreaCenter(ho_Selected, out hv_Area, out hv_Row, out hv_Column);//设置输出对象的线宽为3HOperatorSet.SetLineWidth(winId, 3);//设置区域的填充方式HOperatorSet.SetDraw(winId, "margin");hv_Length.Dispose();hv_Length = 80;//设置输出对象的颜色为蓝色HOperatorSet.SetColor(winId, "orange red");//在窗口上显示十字using (HDevDisposeHelper dh = new HDevDisposeHelper()){HOperatorSet.DispArrow(winId, hv_Row, hv_Column, hv_Row - (hv_Length * hv_Phi.TupleSin()), hv_Column + (hv_Length * (hv_Phi.TupleCos())), 4);}//在窗口上显示回形针的角度 将弧度转为角度deg(Phi)using (HDevDisposeHelper dh = new HDevDisposeHelper()){Disp_message(winId, (((hv_Phi.TupleDeg())).TupleString("3.1f")) + " deg","image", hv_Row, hv_Column - 100, "black", "false");}}catch (HalconException HDevExpDefaultException){//ho_Clip.Dispose();//ho_Dark.Dispose();//ho_Single.Dispose();//ho_Selected.Dispose();//hv_Width.Dispose();//hv_Height.Dispose();//hv_UsedThreshold.Dispose();//hv_Phi.Dispose();//hv_Area.Dispose();//hv_Row.Dispose();//hv_Column.Dispose();//hv_Length.Dispose();throw HDevExpDefaultException;}finally{ho_Clip.Dispose();ho_Dark.Dispose();ho_Single.Dispose();ho_Selected.Dispose();hv_Width.Dispose();hv_Height.Dispose();hv_UsedThreshold.Dispose();hv_Phi.Dispose();hv_Area.Dispose();hv_Row.Dispose();hv_Column.Dispose();hv_Length.Dispose();}
}// Procedures 
// External procedures 
// Chapter: Graphics / Text
// Short Description: Write one or multiple text messages. 
public void Disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem,HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
{// Local control variables HTuple hv_GenParamName = new HTuple(), hv_GenParamValue = new HTuple();HTuple hv_Color_COPY_INP_TMP = new HTuple(hv_Color);HTuple hv_Column_COPY_INP_TMP = new HTuple(hv_Column);HTuple hv_CoordSystem_COPY_INP_TMP = new HTuple(hv_CoordSystem);HTuple hv_Row_COPY_INP_TMP = new HTuple(hv_Row);// Initialize local and output iconic variables try{#region specification//This procedure displays text in a graphics window.////Input parameters://WindowHandle: The WindowHandle of the graphics window, where//   the message should be displayed.//String: A tuple of strings containing the text messages to be displayed.//CoordSystem: If set to 'window', the text position is given//   with respect to the window coordinate system.//   If set to 'image', image coordinates are used.//   (This may be useful in zoomed images.)//Row: The row coordinate of the desired text position.//   You can pass a single value or a tuple of values.//   See the explanation below.//   Default: 12.//Column: The column coordinate of the desired text position.//   You can pass a single value or a tuple of values.//   See the explanation below.//   Default: 12.//Color: defines the color of the text as string.//   If set to [] or '' the currently set color is used.//   If a tuple of strings is passed, the colors are used cyclically//   for every text position defined by Row and Column,//   or every new text line in case of |Row| == |Column| == 1.//Box: A tuple controlling a possible box surrounding the text.//   Its entries://   - Box[0]: Controls the box and its color. Possible values://     -- 'true' (Default): An orange box is displayed.//     -- 'false': No box is displayed.//     -- color string: A box is displayed in the given color, e.g., 'white', '#FF00CC'.//   - Box[1] (Optional): Controls the shadow of the box. Possible values://     -- 'true' (Default): A shadow is displayed in//               darker orange if Box[0] is not a color and in 'white' otherwise.//     -- 'false': No shadow is displayed.//     -- color string: A shadow is displayed in the given color, e.g., 'white', '#FF00CC'.////It is possible to display multiple text strings in a single call.//In this case, some restrictions apply on the//parameters String, Row, and Column://They can only have either 1 entry or n entries.//Behavior in the different cases://   - Multiple text positions are specified, i.e.,//       - |Row| == n, |Column| == n//       - |Row| == n, |Column| == 1//       - |Row| == 1, |Column| == n//     In this case we distinguish://       - |String| == n: Each element of String is displayed//                        at the corresponding position.//       - |String| == 1: String is displayed n times//                        at the corresponding positions.//   - Exactly one text position is specified,//      i.e., |Row| == |Column| == 1://      Each element of String is display in a new textline.//////Convert the parameters for disp_text. #endregionif ((int)((new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(new HTuple())))) != 0){hv_Color_COPY_INP_TMP.Dispose();hv_Column_COPY_INP_TMP.Dispose();hv_CoordSystem_COPY_INP_TMP.Dispose();hv_Row_COPY_INP_TMP.Dispose();hv_GenParamName.Dispose();hv_GenParamValue.Dispose();return;}if ((int)(new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1))) != 0){hv_Row_COPY_INP_TMP.Dispose();hv_Row_COPY_INP_TMP = 12;}if ((int)(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1))) != 0){hv_Column_COPY_INP_TMP.Dispose();hv_Column_COPY_INP_TMP = 12;}////Convert the parameter Box to generic parameters.hv_GenParamName.Dispose();hv_GenParamName = new HTuple();hv_GenParamValue.Dispose();hv_GenParamValue = new HTuple();if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(0))) != 0){if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleEqual("false"))) != 0){//Display no boxusing (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat("box");hv_GenParamName.Dispose();hv_GenParamName = ExpTmpLocalVar_GenParamName;}}using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat("false");hv_GenParamValue.Dispose();hv_GenParamValue = ExpTmpLocalVar_GenParamValue;}}}else if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleNotEqual("true"))) != 0){//Set a color other than the default.using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat("box_color");hv_GenParamName.Dispose();hv_GenParamName = ExpTmpLocalVar_GenParamName;}}using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(hv_Box.TupleSelect(0));hv_GenParamValue.Dispose();hv_GenParamValue = ExpTmpLocalVar_GenParamValue;}}}}if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(1))) != 0){if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleEqual("false"))) != 0){//Display no shadow.using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat("shadow");hv_GenParamName.Dispose();hv_GenParamName = ExpTmpLocalVar_GenParamName;}}using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat("false");hv_GenParamValue.Dispose();hv_GenParamValue = ExpTmpLocalVar_GenParamValue;}}}else if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleNotEqual("true"))) != 0){//Set a shadow color other than the default.using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat("shadow_color");hv_GenParamName.Dispose();hv_GenParamName = ExpTmpLocalVar_GenParamName;}}using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(hv_Box.TupleSelect(1));hv_GenParamValue.Dispose();hv_GenParamValue = ExpTmpLocalVar_GenParamValue;}}}}//Restore default CoordSystem behavior.if ((int)(new HTuple(hv_CoordSystem_COPY_INP_TMP.TupleNotEqual("window"))) != 0){hv_CoordSystem_COPY_INP_TMP.Dispose();hv_CoordSystem_COPY_INP_TMP = "image";}//if ((int)(new HTuple(hv_Color_COPY_INP_TMP.TupleEqual(""))) != 0){//disp_text does not accept an empty string for Color.hv_Color_COPY_INP_TMP.Dispose();hv_Color_COPY_INP_TMP = new HTuple();}//HOperatorSet.DispText(hv_WindowHandle, hv_String, hv_CoordSystem_COPY_INP_TMP,hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP, hv_Color_COPY_INP_TMP, hv_GenParamName,hv_GenParamValue);hv_Color_COPY_INP_TMP.Dispose();hv_Column_COPY_INP_TMP.Dispose();hv_CoordSystem_COPY_INP_TMP.Dispose();hv_Row_COPY_INP_TMP.Dispose();hv_GenParamName.Dispose();hv_GenParamValue.Dispose();return;}catch (HalconException HDevExpDefaultException){hv_Color_COPY_INP_TMP.Dispose();hv_Column_COPY_INP_TMP.Dispose();hv_CoordSystem_COPY_INP_TMP.Dispose();hv_Row_COPY_INP_TMP.Dispose();hv_GenParamName.Dispose();hv_GenParamValue.Dispose();throw HDevExpDefaultException;}
}// Chapter: Graphics / Text
// Short Description: Set font independent of OS 
public void Set_display_font(HTuple hv_WindowHandle, HTuple hv_Size, HTuple hv_Font,HTuple hv_Bold, HTuple hv_Slant)
{// Local control variables HTuple hv_OS = new HTuple(), hv_Fonts = new HTuple();HTuple hv_Style = new HTuple(), hv_Exception = new HTuple();HTuple hv_AvailableFonts = new HTuple(), hv_Fdx = new HTuple();HTuple hv_Indices = new HTuple();HTuple hv_Font_COPY_INP_TMP = new HTuple(hv_Font);HTuple hv_Size_COPY_INP_TMP = new HTuple(hv_Size);// Initialize local and output iconic variables try{//This procedure sets the text font of the current window with//the specified attributes.////Input parameters://WindowHandle: The graphics window for which the font will be set//Size: The font size. If Size=-1, the default of 16 is used.//Bold: If set to 'true', a bold font is used//Slant: If set to 'true', a slanted font is used//hv_OS.Dispose();HOperatorSet.GetSystem("operating_system", out hv_OS);if ((int)((new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(-1)))) != 0){hv_Size_COPY_INP_TMP.Dispose();hv_Size_COPY_INP_TMP = 16;}if ((int)(new HTuple(((hv_OS.TupleSubstr(0, 2))).TupleEqual("Win"))) != 0){//Restore previous behaviorusing (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_Size = ((1.13677 * hv_Size_COPY_INP_TMP)).TupleInt();hv_Size_COPY_INP_TMP.Dispose();hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;}}}else{using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_Size = hv_Size_COPY_INP_TMP.TupleInt();hv_Size_COPY_INP_TMP.Dispose();hv_Size_COPY_INP_TMP = ExpTmpLocalVar_Size;}}}if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier"))) != 0){hv_Fonts.Dispose();hv_Fonts = new HTuple();hv_Fonts[0] = "Courier";hv_Fonts[1] = "Courier 10 Pitch";hv_Fonts[2] = "Courier New";hv_Fonts[3] = "CourierNew";hv_Fonts[4] = "Liberation Mono";}else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))) != 0){hv_Fonts.Dispose();hv_Fonts = new HTuple();hv_Fonts[0] = "Consolas";hv_Fonts[1] = "Menlo";hv_Fonts[2] = "Courier";hv_Fonts[3] = "Courier 10 Pitch";hv_Fonts[4] = "FreeMono";hv_Fonts[5] = "Liberation Mono";}else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0){hv_Fonts.Dispose();hv_Fonts = new HTuple();hv_Fonts[0] = "Luxi Sans";hv_Fonts[1] = "DejaVu Sans";hv_Fonts[2] = "FreeSans";hv_Fonts[3] = "Arial";hv_Fonts[4] = "Liberation Sans";}else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0){hv_Fonts.Dispose();hv_Fonts = new HTuple();hv_Fonts[0] = "Times New Roman";hv_Fonts[1] = "Luxi Serif";hv_Fonts[2] = "DejaVu Serif";hv_Fonts[3] = "FreeSerif";hv_Fonts[4] = "Utopia";hv_Fonts[5] = "Liberation Serif";}else{hv_Fonts.Dispose();hv_Fonts = new HTuple(hv_Font_COPY_INP_TMP);}hv_Style.Dispose();hv_Style = "";if ((int)(new HTuple(hv_Bold.TupleEqual("true"))) != 0){using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_Style = hv_Style + "Bold";hv_Style.Dispose();hv_Style = ExpTmpLocalVar_Style;}}}else if ((int)(new HTuple(hv_Bold.TupleNotEqual("false"))) != 0){hv_Exception.Dispose();hv_Exception = "Wrong value of control parameter Bold";throw new HalconException(hv_Exception);}if ((int)(new HTuple(hv_Slant.TupleEqual("true"))) != 0){using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_Style = hv_Style + "Italic";hv_Style.Dispose();hv_Style = ExpTmpLocalVar_Style;}}}else if ((int)(new HTuple(hv_Slant.TupleNotEqual("false"))) != 0){hv_Exception.Dispose();hv_Exception = "Wrong value of control parameter Slant";throw new HalconException(hv_Exception);}if ((int)(new HTuple(hv_Style.TupleEqual(""))) != 0){hv_Style.Dispose();hv_Style = "Normal";}hv_AvailableFonts.Dispose();HOperatorSet.QueryFont(hv_WindowHandle, out hv_AvailableFonts);hv_Font_COPY_INP_TMP.Dispose();hv_Font_COPY_INP_TMP = "";for (hv_Fdx = 0; (int)hv_Fdx <= (int)((new HTuple(hv_Fonts.TupleLength())) - 1); hv_Fdx = (int)hv_Fdx + 1){hv_Indices.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_Indices = hv_AvailableFonts.TupleFind(hv_Fonts.TupleSelect(hv_Fdx));}if ((int)(new HTuple((new HTuple(hv_Indices.TupleLength())).TupleGreater(0))) != 0){if ((int)(new HTuple(((hv_Indices.TupleSelect(0))).TupleGreaterEqual(0))) != 0){hv_Font_COPY_INP_TMP.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_Font_COPY_INP_TMP = hv_Fonts.TupleSelect(hv_Fdx);}break;}}}if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual(""))) != 0){throw new HalconException("Wrong value of control parameter Font");}using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_Font = (((hv_Font_COPY_INP_TMP + "-") + hv_Style) + "-") + hv_Size_COPY_INP_TMP;hv_Font_COPY_INP_TMP.Dispose();hv_Font_COPY_INP_TMP = ExpTmpLocalVar_Font;}}HOperatorSet.SetFont(hv_WindowHandle, hv_Font_COPY_INP_TMP);hv_Font_COPY_INP_TMP.Dispose();hv_Size_COPY_INP_TMP.Dispose();hv_OS.Dispose();hv_Fonts.Dispose();hv_Style.Dispose();hv_Exception.Dispose();hv_AvailableFonts.Dispose();hv_Fdx.Dispose();hv_Indices.Dispose();return;}catch (HalconException HDevExpDefaultException){hv_Font_COPY_INP_TMP.Dispose();hv_Size_COPY_INP_TMP.Dispose();hv_OS.Dispose();hv_Fonts.Dispose();hv_Style.Dispose();hv_Exception.Dispose();hv_AvailableFonts.Dispose();hv_Fdx.Dispose();hv_Indices.Dispose();throw HDevExpDefaultException;}
}
#endregion

相关文章:

  • 【idea】调试篇 idea调试技巧合集
  • 第五部分:第二节 - Node.js 核心模块:厨房里的基本工具
  • 显示的图标跟UI界面对应不上。
  • 无人机数据处理与特征提取技术分析!
  • Thrust库中的Gather和Scatter操作
  • 【Linux】第十六章 分析和存储日志
  • uniapp vue 沉浸式窗体如何获取并排除外部手机浏览器底部菜单栏工具栏高度
  • sqli—labs第六关——双引号报错注入
  • 小白学习java第18天(上):spring
  • 【C++】17. 多态
  • 大型企业数据治理与数据资产化:数字化转型的炼金术革命
  • 如何解决电脑蓝屏错误代码:Oxc0000098
  • 鸿蒙OSUniApp开发支持多语言的国际化组件#三方框架 #Uniapp
  • elementUI调整滚动条高度后与固定列冲突问题解决
  • 高海拔和远距离的人员识别:面部、体型和步态的融合
  • Java 源码 HashMap源码分析
  • PROE 转 STP 全攻略:软件实操、在线转换与问题解决
  • 【网工第6版】第10章 网络规划和设计②
  • D. Eating【Codeforces Round 1005 (Div. 2)】
  • 微机原理与接口技术知识点总结——8086微处理器ddddd
  • 由我国牵头制定,适老化数字经济国际标准发布
  • 宜昌谱写新叙事:长江大保护与高质量发展如何相互成就
  • 端午假期购票日历发布,今日可购买5月29日火车票
  • 美叙领导人25年来首次会面探索关系正常化,特朗普下令解除对叙经济制裁
  • 在古老的意大利科莫歌剧院,廖昌永唱响16首中国艺术歌曲
  • MSCI中国指数5月调整:新增5只A股、1只港股