<Grid.RowDefinitions>

</Grid.RowDefinitions>

        <Grid>
<UniformGrid Columns="2">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<InkCanvas Name="ink" Background="Transparent" Cursor="Pen" ForceCursor="True">
<Image Name="ImgShow" Source="/temp.png" IsHitTestVisible="False"> </Image>
</InkCanvas>
</ScrollViewer>
<UniformGrid Rows="2">
<GroupBox Header="Mask" >
<Image x:Name="imgMask"></Image>
</GroupBox>
<GroupBox Header="Result">
<Image x:Name="imgResult"></Image>
</GroupBox>
</UniformGrid>
</UniformGrid> </Grid>
<StackPanel Grid.Row="1" Margin="20">
<DockPanel >
<Grid Grid.Row="1" VerticalAlignment="Center" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0" VerticalAlignment="Center" Content="绘制墨迹" Click="RadioButton_Click" IsChecked="True"/>
<RadioButton Grid.Column="1" Content="按点擦除" Click="RadioButton_Click"/>
<RadioButton Grid.Column="2" Content="按线擦除" Click="RadioButton_Click"/>
<RadioButton Grid.Column="3" Content="选中墨迹" Click="RadioButton_Click"/>
<RadioButton Grid.Column="4" Content="停止操作" Click="RadioButton_Click"/>
</Grid>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0">颜色选择:</TextBlock>
<Border CornerRadius="5" x:Name="colorchk" Background="Black" Width="50" HorizontalAlignment="Left" MouseLeftButtonDown="Grid_MouseLeftButtonDown" ></Border> </DockPanel>
<DockPanel>
<Button Margin="20 0 0 0" Width="100" Height="30" Click="Button_Click">Roi截取</Button>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0">兴趣区域平均值:<Run Foreground="#e03997" Name="txt_meanValue"></Run></TextBlock>
<Slider Value="120" x:Name="threshould_slider" Width="200" TickPlacement="Both" TickFrequency="1" Maximum="255" IsSnapToTickEnabled="True"></Slider>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">阈值<Run Text="{Binding ElementName=threshould_slider,Path=Value}"></Run></TextBlock>
<Button Margin="20 0 0 0" Width="100" HorizontalAlignment="Left" Height="30" Click="floodfill_Click">漫水填充</Button>
</DockPanel>
</StackPanel> </Grid> </Grid>

//cs代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using Emgu.CV.Util;
using Color = System.Drawing.Color;
using Point = System.Drawing.Point;
using Rectangle = System.Drawing.Rectangle;

namespace MaskGetMean
{
///

/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
//声明一个 DrawingAttributes 类型的变量
DrawingAttributes drawingAttributes;
///
/// 默认图像路径。可拖拽图像进窗体
///
string imgpath = (AppDomain.CurrentDomain.BaseDirectory + "temp.png");

    public MainWindow()
{
InitializeComponent();
//创建 DrawingAttributes 类的一个实例
drawingAttributes = new DrawingAttributes();
//将 InkCanvas 的 DefaultDrawingAttributes 属性的值赋成创建的 DrawingAttributes 类的对象的引用
//InkCanvas 通过 DefaultDrawingAttributes 属性来获取墨迹的各种设置,该属性的类型为 DrawingAttributes 型
ink.DefaultDrawingAttributes = drawingAttributes;
//设置 DrawingAttributes 的 Color 属性设置颜色 }
/// <summary>
/// 拖拽
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainWindow_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effects = DragDropEffects.Link; //WinForm中为e.Effect = DragDropEffects.Link
else e.Effects = DragDropEffects.None; //WinFrom中为e.Effect = DragDropEffects.None
} private void MainWindow_Drop(object sender, DragEventArgs e)
{
string fileName = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
if (fileName.EndsWith(".jpg") || fileName.EndsWith(".png") || fileName.EndsWith(".bmp"))
{
imgpath = fileName;
ImgShow.Source = new BitmapImage(new Uri(imgpath)); //The Imageviewer 直接弹出新的窗口
Image<Bgr, byte> loadImg = new Image<Bgr, byte>(imgpath);
ImageViewer viewer = new ImageViewer(loadImg, "Loaded Image");
viewer.Show(); //1.使用HistogramViewer不需要事先拉到设计窗口中,他是弹出窗口,你只需要直接使用便可以
HistogramViewer.Show(loadImg[0], 32); //image[0] 显示Blue,bin = 32
HistogramViewer.Show(loadImg, 32); //显示所有信道
//获得文件名后的操作...
} }
private void Button_Click(object sender, RoutedEventArgs e)
{
//原始图像
var OldImage = CvInvoke.Imread(imgpath);
//获取图像原始大小和显示大小的比例
double a = OldImage.Width / ImgShow.Source.Width;
//获取画的坐标线集合
var list = ink.Strokes;
//装轮廓集合
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint(); //获取画的坐标点集合
foreach (var item in list)
{ //单个轮廓坐标集合
VectorOfPoint vectorOfPoint = new VectorOfPoint();
foreach (var stylusPoint in item.StylusPoints)
{
vectorOfPoint.Push(new System.Drawing.Point[] { new System.Drawing.Point((int)(stylusPoint.X * a), (int)(stylusPoint.Y * a)) });
}
if (vectorOfPoint.Size <= 0)
break;
contours.Push(vectorOfPoint);
}
//准备掩膜图像
Image<Gray, byte> mask = new Image<Gray, byte>(OldImage.Width, OldImage.Height);
//设置全黑
mask.SetZero();
//把轮廓全部绘制成白色在mask上变成感兴趣的区域 类似roi
for (int i = 0; i < contours.Size; i++)
{
CvInvoke.DrawContours(mask, contours, i, new MCvScalar(255, 255, 255), -1, LineType.AntiAlias, null, int.MaxValue);
}
//准备结果图像
Image<Bgr, byte> Result = new Image<Bgr, byte>(OldImage.Width, OldImage.Height);
//显示
imgMask.Source = BitmapToBitmapImage(mask.ToBitmap());
//CvInvoke.Imshow("DrawContours", mask);
//获取感兴趣的区域到结果图
OldImage.CopyTo(Result, mask);
//显示
//CvInvoke.Imshow("mask", Result);
imgResult.Source = BitmapToBitmapImage(Result.ToBitmap());
txt_meanValue.Text = CvInvoke.Mean(Result).V0.ToString();
}
/// <summary>
/// 左键选择画笔颜色
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
System.Windows.Forms.ColorDialog colorDialog = new System.Windows.Forms.ColorDialog();
if (colorDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
System.Drawing.SolidBrush sb = new System.Drawing.SolidBrush(colorDialog.Color);
SolidColorBrush solidColorBrush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(sb.Color.A, sb.Color.R, sb.Color.G, sb.Color.B));
colorchk.Background = solidColorBrush;
drawingAttributes.Color = new System.Windows.Media.Color() { A = sb.Color.A, B = sb.Color.B, G = sb.Color.G, R = sb.Color.R };
}
} /// <summary>
/// Bitmap转BitmapImage 用于Image控件成像
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
public static BitmapSource BitmapToBitmapImage(System.Drawing.Bitmap bitmap)
{
if (bitmap == null)
return null;
try
{
using (System.Drawing.Bitmap source = bitmap)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); DeleteObject(ptr); //release the HBitmap
return bs;
}
}
catch (Exception)
{ return null;
} }
[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);
/// <summary>
/// ink画板事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RadioButton_Click(object sender, RoutedEventArgs e)
{
if ((sender as RadioButton).Content.ToString() == "绘制墨迹")
{
ink.ForceCursor = true;
ink.EditingMode = InkCanvasEditingMode.Ink;
}
else
{
ink.ForceCursor = false;
if ((sender as RadioButton).Content.ToString() == "按点擦除")
{
ink.EditingMode = InkCanvasEditingMode.EraseByPoint;
} else if ((sender as RadioButton).Content.ToString() == "按线擦除")
{
ink.EditingMode = InkCanvasEditingMode.EraseByStroke;
} else if ((sender as RadioButton).Content.ToString() == "选中墨迹")
{
ink.EditingMode = InkCanvasEditingMode.Select;
} else if ((sender as RadioButton).Content.ToString() == "停止操作")
{
ink.EditingMode = InkCanvasEditingMode.None;
}
} }
/// <summary>
/// 漫水填充
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void floodfill_Click(object sender, RoutedEventArgs e)
{
int threshould = (int)threshould_slider.Value;
var color = System.Drawing.Color.White;
//原始图像
var OldImage = CvInvoke.Imread(imgpath);
//获取图像原始大小和显示大小的比例
double a = OldImage.Width / ImgShow.Source.Width;
//获取画的坐标线集合
var list = ink.Strokes;
//装轮廓集合
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//获取画的坐标点集合
foreach (var item in list)
{ //单个轮廓坐标集合
VectorOfPoint vectorOfPoint = new VectorOfPoint();
foreach (var stylusPoint in item.StylusPoints)
{
vectorOfPoint.Push(new System.Drawing.Point[] { new System.Drawing.Point((int)(stylusPoint.X * a), (int)(stylusPoint.Y * a)) });
}
if (vectorOfPoint.Size <= 0)
break;
contours.Push(vectorOfPoint);
}
if (contours.Size == 0) return;
//清空点
ink.Strokes.Clear();
//计算点的阈值平均值(不太好用 也就是没写好) //var GrayOldImage = OldImage.Clone();
//if (GrayOldImage.NumberOfChannels == 3)
// CvInvoke.CvtColor(GrayOldImage, GrayOldImage, ColorConversion.Rgb2Gray);
//int rows = GrayOldImage.Rows, cols = GrayOldImage.Cols, step = GrayOldImage.Step;
//threshould = 0;
//long count = 0;
//for (int i = 0; i < contours.Size; i++)
//{
// for (int j = 0; j < contours[i].Size; j++)
// { // unsafe
// {
// byte* dataptr = (byte*)GrayOldImage.DataPointer;
// ///单通道图像遍历方式
// int index = contours[i][j].X * step + contours[i][j].Y;
// value += dataptr[index];
// }
// }
// count += contours[i].Size;
//}
//value = value / count;
var data = FloodFill(OldImage.ToBitmap(), contours[0][0], color, threshould);
if (data != null)
{
VectorOfVectorOfPoint NewVec = new VectorOfVectorOfPoint();
CvInvoke.FindContours(data.ToImage<Gray, byte>(), NewVec, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxTc89Kcos);
CvInvoke.DrawContours(OldImage, NewVec, 0, new MCvScalar(0, 255, 0), 1, LineType.AntiAlias, null, 1);
//显示
imgMask.Source = BitmapToBitmapImage(OldImage.ToBitmap());
//显示
imgResult.Source = BitmapToBitmapImage(OldImage.ToBitmap());
txt_meanValue.Text = CvInvoke.Mean(OldImage).V0.ToString();
//-----------获取roi---------------
//准备掩膜图像
Image<Gray, byte> mask = new Image<Gray, byte>(OldImage.Width, OldImage.Height);
//设置全黑
mask.SetZero();
//把轮廓全部绘制成白色在mask上变成感兴趣的区域 类似roi
for (int i = 0; i < NewVec.Size; i++)
{
CvInvoke.DrawContours(mask, NewVec, i, new MCvScalar(255, 255, 255), -1, LineType.AntiAlias, null, int.MaxValue);
}
//准备结果图像
Image<Bgr, byte> Result = new Image<Bgr, byte>(OldImage.Width, OldImage.Height); //获取感兴趣的区域到结果图
OldImage.CopyTo(Result, mask);
//显示
//CvInvoke.Imshow("mask", Result);
imgResult.Source = BitmapToBitmapImage(Result.ToBitmap());
} } /// <summary>
///
/// </summary>
/// <param name="src">原图</param>
/// <param name="location">检测点</param>
/// <param name="fillColor">填充颜色</param>
/// <param name="threshould"阈值></param>
/// <returns>填充图,非填充部分为默认值</returns>
unsafe public Bitmap FloodFill(Bitmap src, Point location, Color fillColor, int threshould)
{
try
{
Bitmap srcbmp = src;
Color backColor = srcbmp.GetPixel(location.X, location.Y);
Bitmap dstbmp = new Bitmap(src.Width, src.Height);
int w = srcbmp.Width; int h = srcbmp.Height;
Stack<Point> fillPoints = new Stack<Point>(w * h);
System.Drawing.Imaging.BitmapData bmpData = srcbmp.LockBits(new Rectangle(0, 0, srcbmp.Width, srcbmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Drawing.Imaging.BitmapData dstbmpData = dstbmp.LockBits(new Rectangle(0, 0, dstbmp.Width, dstbmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
int stride = bmpData.Stride; int stridedst = dstbmpData.Stride; byte* srcbuf = (byte*)bmpData.Scan0.ToPointer();
int* dstbuf = (int*)dstbmpData.Scan0.ToPointer();
int cr = backColor.R, cg = backColor.G, cb = backColor.B, ca = backColor.A;
byte fcr = fillColor.R, fcg = fillColor.G, fcb = fillColor.B; int fc = fillColor.ToArgb();
if (location.X < 0 || location.X >= w || location.Y < 0 || location.Y >= h) return null; fillPoints.Push(new Point(location.X, location.Y)); int[,] mask = new int[w, h];
while (fillPoints.Count > 0)
{
Point p = fillPoints.Pop();
mask[p.X, p.Y] = 1;
dstbuf[p.X + p.Y * w] = fc;
if (p.X > 0 && (mask[p.X - 1, p.Y] != 1) && Math.Abs(cb - srcbuf[4 * (p.X - 1) + p.Y * stride]) + Math.Abs(cg - srcbuf[4 * (p.X - 1) + 1 + p.Y * stride]) + Math.Abs(cr - srcbuf[4 * (p.X - 1) + 2 + p.Y * stride]) < threshould && Math.Abs(ca - srcbuf[4 * (p.X - 1) + 3 + p.Y * stride]) < threshould)
{
dstbuf[(p.X - 1) + p.Y * w] = fc;
fillPoints.Push(new Point(p.X - 1, p.Y)); mask[p.X - 1, p.Y] = 1;
}
if (p.X < w - 1 && (mask[p.X + 1, p.Y] != 1) && Math.Abs(cb - srcbuf[4 * (p.X + 1) + p.Y * stride]) + Math.Abs(cg - srcbuf[4 * (p.X + 1) + 1 + p.Y * stride]) + Math.Abs(cr - srcbuf[4 * (p.X + 1) + 2 + p.Y * stride]) < threshould && Math.Abs(ca - srcbuf[4 * (p.X + 1) + 3 + p.Y * stride]) < threshould)
{ dstbuf[(p.X + 1) + p.Y * w] = fc; fillPoints.Push(new Point(p.X + 1, p.Y)); mask[p.X + 1, p.Y] = 1; }
if (p.Y > 0 && (mask[p.X, p.Y - 1] != 1) && Math.Abs(cb - srcbuf[4 * p.X + (p.Y - 1) * stride]) + Math.Abs(cg - srcbuf[4 * p.X + 1 + (p.Y - 1) * stride]) + Math.Abs(cr - srcbuf[4 * p.X + 2 + (p.Y - 1) * stride]) < threshould && Math.Abs(ca - srcbuf[4 * p.X + 3 + (p.Y - 1) * stride]) < threshould)
{ dstbuf[p.X + (p.Y - 1) * w] = fc; fillPoints.Push(new Point(p.X, p.Y - 1)); mask[p.X, p.Y - 1] = 1; }
if (p.Y < h - 1 && (mask[p.X, p.Y + 1] != 1) && Math.Abs(cb - srcbuf[4 * p.X + (p.Y + 1) * stride]) + Math.Abs(cg - srcbuf[4 * p.X + 1 + (p.Y + 1) * stride]) + Math.Abs(cr - srcbuf[4 * p.X + 2 + (p.Y + 1) * stride]) < threshould && Math.Abs(ca - srcbuf[4 * p.X + 3 + (p.Y + 1) * stride]) < threshould)
{ dstbuf[p.X + (p.Y + 1) * w] = fc; fillPoints.Push(new Point(p.X, p.Y + 1)); mask[p.X, p.Y + 1] = 1; }
}
fillPoints.Clear(); srcbmp.UnlockBits(bmpData); dstbmp.UnlockBits(dstbmpData); return dstbmp;
}
catch
{
return null;
}
}
}

}

WPF+Emgucv实现在图像上画出感兴趣的区域 并进行掩膜获取 得到图像均值 和简单的 漫水填充的更多相关文章

  1. Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解

    在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...

  2. 使用JavaScript在Canvas上画出一片星空

    随着Html5的迅猛发展,画布也变得越来越重要.下面我就写一个关于在canvas上画出一片星空的简单的代码的示例. 理论基础 初始化一个canvas,获得一个用于绘制图形的上下文环境context.并 ...

  3. 【wpf】在win10系统上弹出toast和notification

    原文:[wpf]在win10系统上弹出toast和notification 老规矩,先看效果 右下角的notification: 操作中心的notification: 整体效果: 前提条件 1.需要在 ...

  4. Python 图像处理 OpenCV (3):图像属性、图像感兴趣 ROI 区域及通道处理

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 图像属性 图像 ...

  5. WPF在圆上画出刻度线

    思路 我们可以使用Ellipse先画出一个圆当背景,然后用Canvas再叠加画上刻度线,就能得到如下的效果 我们先用Ellipse画一个橙色的圆,然后将Canvas的宽度和高度绑定到Ellipse的宽 ...

  6. OpenCV之响应鼠标(四):在图像上绘制出矩形并标出起点的坐标

    涉及到两方面的内容:1. 用鼠标画出矩形.2.在图像上绘制出点的坐标 用鼠标绘制矩形,涉及到鼠标的操作,opencv中有鼠标事件的介绍.需要用到两个函数:回调函数CvMouseCallback和注册回 ...

  7. Android教程:在百度地图上画出轨迹

    [日期:2013-04-14] 来源:Linux社区  作者:crazyxin1988 [字体:大 中 小]     接着上面的项目<Android访问webservice.客户端登录注册> ...

  8. canvas上画出坐标集合,并标记新坐标,背景支持放大缩小拖动功能

    写在前面:项目需求,用户上传一个区位的平面图片,用户可以在图片上添加新的相机位置,并且展示之前已绑定的相机坐标位置,图片支持放大缩小&拖动的功能.新增坐标,页面展示相对canvas定位,保存时 ...

  9. 还没被玩坏的robobrowser(4)——从页面上抓取感兴趣的内容

    背景 本节的知识实际上是属于Beautiful Soup的内容. robobrowser支持Beautiful Soup,一般来说通过下面3个方法获取页面上感兴趣的内容 find find_all s ...

  10. [Java]在窗口界面上画出硬盘中图片文件

    利用类javax.swing.JPanel来在窗口界面上画图.图片文件通过javax.imageio.ImageIO类来获取. import java.awt.Graphics; import jav ...

随机推荐

  1. 报表输入页码翻页(润乾 V2018)

    报表数据分了太多页,一页一页翻页查看数据嫌麻烦,可以试试这种翻页效果--输入页码翻页. 润乾报表提供了翻页相关的 JS 函数,可以在报表展现的页面中添加 JS 调用翻页函数实现输入页码跳转到对应页. ...

  2. LeetCode:999. 车的可用捕获量

    999. 车的可用捕获量 在一个 8 x 8 的棋盘上,有一个白色车(rook).也可能有空方块,白色的象(bishop)和黑色的卒(pawn).它们分别以字符 "R"," ...

  3. vue+scss混合(mixins)使用(css代码的vuex(公共管理))

    scss混合(mixins)使用 例一.使用混合mixins中的变量来定义一个n行文本溢出隐藏的公用样式. 1.创建mixins.scss文件 //文本n行溢出隐藏 @mixin ellipsisBa ...

  4. 【笔记】go语言--(Slice)切片的概念

    go--(Slice)切片的概念 //切片是什么,定义一个arr,定义一个s为arr中的2到6,这个s就是一个切片 arr := [...]int{0,1,2,3,4,5,6,7} s := arr[ ...

  5. WPF 通过 GetMessageExtraInfo 方法获取当前收到的鼠标消息是否由触摸转换过来

    本文将告诉大家如何在 WPF 或者其他 Win32 应用里面,在收到鼠标消息时,通过 GetMessageExtraInfo 方法获取当前收到的鼠标消息是否由触摸消息提升而来 大家都知道,在不开启 W ...

  6. dotnet 6 引用 NAudio 的旧版本构建不通过

    本文告诉大家在使用 NAudio 的旧版本导致构建不通过问题,解决方法是升级到 1.10 或以上版本 在更新 dotnet 6 项目时,使用了 NAudio 的旧版本,构建失败,提示 MC1000 如 ...

  7. MQTT GUI 客户端 可视化管理工具

    MQTT GUI 客户端 可视化管理工具 介绍 多标签页管理,同时打开多个连接 提供原生性能,并且比使用 Electron 等 Web 技术开发的同等应用程序消耗的资源少得多 支持 MQTT v5.0 ...

  8. SonarQube+Maven+SonarQube Scanner

    1.SonarQube简介 官方网站地址:https://www.sonarqube.org/ SonrQube是一个开源的代码质量管理系统,用于检测代码中的错误,漏洞和代码规范.它可以以现有的Git ...

  9. 习题8 #第8章 Verilog有限状态机设计-2 #Verilog #Quartus #modelsim

    2. 设计一个"1001"串行数据检测器,其输入.输出如下: 输入x:000 101 010 010 011 101 001 110 101 输出z:000 000 000 010 ...

  10. SQL语法之:连表查询:union all

    1.准备 两条sql查询出来的字段数必须一致 表1 字段: 数据: 表2 字段: 数据: 2.使用 1.两张表结构完全一样,查询字段顺序也一样 select ID,NAME,SEX,AGE,NAME2 ...