其实前面讲的自动对焦的梯度和与线图像中的梯度和是不一样的(两者梯度也不一样),如果你囫囵吞枣,我就要称你“马虎哥”了。实质上,梯度和携带了方向,他不是角度方向,白(255)-黑(0)=255,是正值,方向是白到黑,相反,为负值,则是黑到白。自动对焦中使用绝对值更能体现清晰度,而线图像中梯度和出现最大值,则是白到黑的边界,如果这个最大值带有负号,则出现了黑到白的边界。
好了,为了区分感兴趣区域(ROI),我们重新设计了两条线(|——)来演示线图像。“|”为startLine,为线图像,“——”rccentreLine,非线图像,其中心为m_rcCentre,这条非线图像,用来操作线图像。这是一个“丁”字型设计,为什么要这样设计?原因有二,一,验证他们说的,梯度方向垂直边缘。其二,线图像被拖动旋转时,另一条画线用来验证正确性。代码如下:(如有不懂,参考感兴趣区域(ROI)代码)(梯度方向,这是角度,Gy=图像【x,y+1】-图像【x,y】,Gx=图像【x+1,y】-图像【x,y】,theta=arctan(Gy/Gx))
public class RoiBase//为自己的线图像服务
{
public mg_line RcCentreLine;//-------非线图像
public mg_line startLine;//|------- 线图像
public PointF m_RcCenter;//非线图像中心
public RoiBase()//构造函数,初始化centreline和startline
{
PointF start = new PointF(10, 40);
PointF end = new PointF(70, 40);
RcCentreLine = new mg_line(start, end);
m_RcCenter = new PointF((start.X + end.X) / (float)2, (start.Y + end.Y) / (float)2);
start = new PointF(10, 10);
end = new PointF(10, 70);
startLine = new mg_line(start, end);
}
public int IsPointInRect(PointF point)//判断操作是否在相应区域
{
if (point.X <= m_RcCenter.X + 5 && point.X >= m_RcCenter.X - 5
&& point.Y >= m_RcCenter.Y - 5 && point.Y <= m_RcCenter.Y + 5)
{
return (int)E_HANDLES.E_HANDLE_INSIDE;
}
else if (point.X <= RcCentreLine.pt_end.X + 5 && point.X >= RcCentreLine.pt_end.X - 5
&& point.Y >= RcCentreLine.pt_end.Y - 5 && point.Y <= RcCentreLine.pt_end.Y + 5)
{
return (int)E_HANDLES.E_HANDLE_EAST;// E_HANDLE_EAST,3
}
else
{
return 0;
}
}
public double jiaoduAndxiangxian(double x_temp, double y_temp)//角度和象限
{
double retTheta = 0;
if (x_temp > 0 && y_temp > 0)
{
return retTheta = Math.Atan2(y_temp, x_temp);
}
else if (x_temp > 0 && y_temp == 0)
{
return retTheta = 0;
}
else if (x_temp < 0 && y_temp > 0)
{
return retTheta = Math.Atan2(y_temp, x_temp);
}
else if (x_temp == 0 && y_temp > 0)
{
return retTheta = 3.1415926 / 2.0;
}
else if (x_temp < 0 && y_temp < 0)
{
return retTheta = 2 * 3.1415926 + Math.Atan2(y_temp, x_temp);
}
else if (x_temp < 0 && y_temp == 0)
{
return retTheta = 3.1415926;
}
else if (x_temp > 0 && y_temp < 0)
{
return retTheta = 2 * 3.1415926 + Math.Atan2(y_temp, x_temp);
}
else if (x_temp == 0 && y_temp < 0)
{
return retTheta = 3 * 3.1415926 / 2.0;
}
else { return retTheta; }
}
public double m_jiaodu = 0;
public void DragXYandRotate(PointF point)//改变centreline终点(x,y),角度
{
double fenziY, fenmuX;
RcCentreLine.updatePend(point);
fenziY = (RcCentreLine.pt_end.Y - RcCentreLine.pt_start.Y);
fenmuX = RcCentreLine.pt_end.X - RcCentreLine.pt_start.X;
double thetatheta1 = 0;
thetatheta1 = jiaoduAndxiangxian(fenmuX, fenziY);
double DeltaTheta1 = 0;
m_jiaodu = DeltaTheta1 = thetatheta1;
updateRoi((float)DeltaTheta1); //更新相关
}
public void RoiReset(float deltaChang, float deltaKuan)//线图像工具重置
{
PointF start = new PointF(RcCentreLine.pt_start.X, RcCentreLine.pt_start.Y);
PointF end = new PointF(RcCentreLine.pt_start.X + 60 + deltaChang, RcCentreLine.pt_start.Y);
RcCentreLine = new mg_line(start, end);
m_RcCenter = new PointF((start.X + end.X) / (float)2, (start.Y + end.Y) / (float)2);
start = new PointF(RcCentreLine.pt_start.X, RcCentreLine.pt_start.Y - 30 - deltaKuan / (float)2);
end = new PointF(RcCentreLine.pt_start.X, RcCentreLine.pt_start.Y + 30 + deltaKuan / (float)2);
startLine = new mg_line(start, end);
}
public float getLineLength(mg_line templine)//获取线长度
{
float xx = templine.pt_start.X - templine.pt_end.X;
float yy = templine.pt_start.Y - templine.pt_end.Y;
return (float)Math.Sqrt(xx * xx + yy * yy);
}
public void updateRoi(float rotationAngle)//更新我们设计的线图像工具
{
//置零后,再旋转这么多度。20160622也就不需要delta增量
float chang = getLineLength(RcCentreLine);//获取直线长度
float kuan = getLineLength(startLine);//获取直线宽度
chang = chang - 60;//原来长度60
kuan = kuan - 60;//原来宽度60
RoiReset(chang, kuan);//怎样保持已更改后的大小
// double k1;
RcCentreLine.Rotate(RcCentreLine.pt_start, rotationAngle);
startLine.Rotate(RcCentreLine.pt_start, rotationAngle);
//m_RcCenter
PointF start = (RcCentreLine.pt_start);
PointF end = (RcCentreLine.pt_end);
m_RcCenter = new PointF((start.X + end.X) / (float)2, (start.Y + end.Y) / (float)2);
}
public void Drag(PointF point)//拖动线图像工具
{
PointF delta = new PointF(point.X - m_RcCenter.X, point.Y - m_RcCenter.Y);
RcCentreLine.Move(delta);
startLine.Move(delta);
this.m_RcCenter.X = point.X;
this.m_RcCenter.Y = point.Y;
}
public void DrawLineAndRect(Graphics g, Pen p, int Dir)//画出线图像工具
{
g.DrawLine(p, RcCentreLine.pt_start, RcCentreLine.pt_end);
g.DrawLine(p, startLine.pt_start, startLine.pt_end);
//Centre
g.DrawRectangle(p, (int)m_RcCenter.X - 5, (int)m_RcCenter.Y - 5, 10, 10);
//Right
g.DrawRectangle(p, (int)RcCentreLine.pt_end.X - 5, (int)RcCentreLine.pt_end.Y - 5, 10, 10);
}
}
里边有一个mg_line,是什么鬼?他来源于计算机图形学基础教材,一个直线类。
public class mg_line
{
public PointF pt_start;
public PointF pt_end;
public mg_line()
{
pt_end = new PointF();
pt_start = new PointF();
}
public mg_line(PointF pstart, PointF pend)
{
pt_start = pstart;
pt_end = pend;
}
public void updatePstart(PointF pstart)
{
pt_start = pstart;
}
public void updatePend(PointF pend)
{
pt_end = pend;
}
public void Translate(TransMat Mat)
{
Mat.TransPoint(ref pt_start);
Mat.TransPoint(ref this.pt_end);
}
public void Move(PointF ZhiDingDian)
{
TransMat M=new TransMat();
M.Movement(ZhiDingDian.X, ZhiDingDian.Y);
this.Translate(M);
}
public void Scale(PointF pBase, double xScale, double yScale)
{
TransMat M = new TransMat();
M.Scale(xScale, yScale);
this.Translate(M);
}
public void Rotate(PointF pBase, double angle)
{
TransMat M = new TransMat();
M.RotateBase(angle, pBase);
this.Translate(M);
}
}
TransMat是什么鬼?他来源于计算机图形学基础教材,一个矩阵变换类。
public class TransMat
{
const double PI = 3.1415926;
public double[,] Mat = new double[3, 3];
public TransMat()
{
int i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
if (i == j) Mat[i,j] = 1;
else Mat[i,j] = 0;
}
}
public void FuZhiToMat(TransMat scrMat)
{
int i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
Mat[i, j] = scrMat.Mat[i, j];
}
}
public void Identity()
{
int i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
if (i == j) Mat[i, j] = 1;
else Mat[i, j] = 0;
}
}
public void Multiply(TransMat scrMat)
{
int i, j, k;
double[,] M=new double[3,3];
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
M[i,j] = 0;
for (k = 0; k < 3; k++)
{
M[i,j] += Mat[i,k] * scrMat.Mat[k, j];
}
}
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
Mat[i,j] = M[i,j];
}
}
public void Movement(double dx, double dy)
{
TransMat M=new TransMat();
M.Mat[2,0] = dx;
M.Mat[2,1] = dy;
Multiply(M);
}
public void Movement(PointF pt)
{
TransMat M = new TransMat();
M.Mat[2, 0] = pt.X;
M.Mat[2, 1] = pt.Y;
Multiply(M);
}
public void Scale(double sx, double sy)
{
TransMat M=new TransMat();
M.Mat[0,0] = sx;
M.Mat[1,1] = sy;
this.Multiply(M);
}
public void Scale(double s)
{
TransMat M = new TransMat();
M.Mat[0, 0] = s;
M.Mat[1, 1] = s;
this.Multiply(M);
}
public void Rotate(double alf)
{
TransMat M=new TransMat();
M.Mat[0, 0] = M.Mat[1, 1] = Math.Cos(alf);//Math.Cos
M.Mat[0, 1] = Math.Sin(alf);//Math.Sin
M.Mat[1,0] = -M.Mat[0,1];
this.Multiply(M);
}
public void RotateBase(double alf, PointF Base)
{
this.Movement(-Base.X, -Base.Y);
this.Rotate(alf);
this.Movement(Base.X, Base.Y);
}
public void LeftMultiply(TransMat scrMat)
{
int i, j, k;
double[,] M = new double[3, 3];
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
M[i, j] = 0;
for (k = 0; k < 3; k++)
{
M[i, j] += scrMat.Mat[i, k] * Mat[k, j];
}
}
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
{
Mat[i, j] = M[i, j];
}
}
public void TransPoint(ref PointF sp)
{
double x, y;
x = this.Mat[0,0] * sp.X + this.Mat[1,0] * sp.Y + this.Mat[2,0];
y = this.Mat[0,1] * sp.X + this.Mat[1,1] * sp.Y + this.Mat[2,1];
sp.X = (float)x;
sp.Y = (float)y;
}
}
未完(待续.........................)