第五神奇----图像上任意点的自由缩放(zoom)技术(感兴趣区域(roi)尺度变化)

总结让人进步,写出来给人看,更是受益匪浅。

2017年11月12日夜十点,程序调试断点过后,鼠标已经走位,缩放的观察观察失去了意义,虽然尝试有一些进展,但都是零星的,保存关机,打算明日再来。坐到床上,找到笔和稿纸,打算再推演一下,不知道,当时起笔,为什么会首先写下这几个字:A是参考点,A*S是放大后的图像...至今不明白这神来之笔,而后的逻辑推演草草十来行,问题便解决了。

后来又有两次总结进步,但仍不能明白为什么会有这样的发端。今天,又是一次总结。这似乎有点像和尚悟道,不明,师傅棒喝!突然悟道!这也很像乌云密布造势之后而来的最后一道刺眼的闪电,雨下而来!找不到发端,就不找了,该来的会来,功到自然成。

人家都说,第一次做,一定做到最好,我很信服这话,因为里边的神来之笔,后来不再有。

进入正题:一,A是参考点,A*S是放大后的图像,A*(S-1)移动出窗口之外,保持A点在窗口不动。比如图像1024*768,放大2倍,有1024*768出窗口,还有1024*768在窗口内,假定A在(200,200),放大后为(400,400),要保持不变,即要出窗口(200,200),这样A点会在窗口不动,在窗口的图像是(200,200,200+1024,200+768),其余截去。

二,然后鼠标移动到窗口一点e(x,y),它对应原图像B点,即B*S-A*(S-1),然后放大到S',那么B点如何保持不动呢?首先移动出窗口B*(S'-1),其次,再移动出窗口B*S-A*(S-1)-B,它相当于以B为参考点,那么在S时,deltaAB要移动出窗口,整理一下(B-A)(S-1)=deltaAB,所以以B为参考点,总共移动出窗口B*(S'-1)+B*S-A*(S-1)-B,令它等于★。这样保持B在放大S'时保持不动。

三,然后鼠标移动到窗口一点e1(x,y),它对应原图像C点,放大S时,C点在C*S-A*(S-1)【以A为参考,减去移动出窗口量A*(S-1)】;放大S'时,C点在C*S'-★【以B为参考,减去移动出窗口量★】;然后放大到S‘’,那么C点如何保持不动呢?首先移动出窗口C*(S''-1),其次,以C为参考点,那么在S'时,deltaBC要移动出窗口C*S'-★-C=deltaBC,总共移动出窗口C*(S''-1)+C*S'-★-C。

这样保持C在放大S‘’时保持不动。图像变成1024*768*S‘’,窗口内仍然1024*768,有1024*768*(S‘’-1)在窗口外。

四,鼠标再移动,令它C*(S''-1)+C*S'-★-C=★★,依次类推......缩小亦是此道理。

下面是C#代码:图像在pictureBox1中,分辨率1024*768

一,  Point Xpt = new Point();
        Point pt0 = new System.Drawing.Point();  

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            pictureBox1.Focus();
            if (Xpt.X != e.X && Xpt.Y != e.Y)
            {
                Xpt.X = e.X;
                Xpt.Y = e.Y;
                if (glob_ScaleX > 1)
                {
                    Xpt.X = (Xpt.X + pt0.X) / (int)glob_ScaleX;
                    Xpt.Y = (Xpt.Y + pt0.Y) / (int)glob_ScaleX;
                }
            }

}

二,private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0)
            {
                glob_ScaleX += (float)(e.Delta / 120.0);
                if (0 == glob_ScaleX) glob_ScaleX = 1;
            }
            else
            {
                glob_ScaleX -= (float)((-e.Delta) / 120.0);               
                if (0 == glob_ScaleX) glob_ScaleX = 1;
            }
            Point tempPt = new System.Drawing.Point(Xpt.X - e.X, Xpt.Y - e.Y);
           
            pictureBox1.Image = ZoomImg(new Size(glob_curBitmap.Width, glob_curBitmap.Height), (int)glob_ScaleX,
                new Point(Xpt.X, Xpt.Y), tempPt);

            m_btempImage3 = true;
            pt0.Y = ((int)glob_ScaleX - 1) * (Xpt.Y) + Xpt.Y - e.Y;
            pt0.X = ((int)glob_ScaleX - 1) * (Xpt.X) + Xpt.X - e.X;

}

三,   public Bitmap ZoomImg(Size srcbitmap, int multiple, Point pt, Point deltaPt)
        {//继续改进版20171027//问题多多,但关键点已经突破。201710280716

        //问题已经使用数学的方法解决。201711130731
            if (multiple <= 0) { multiple = 0; pt0 = new System.Drawing.Point(); return glob_curBitmap; }
            int tempW = (int)(srcbitmap.Width * multiple);
            int tempH = (int)(srcbitmap.Height * multiple);
            int orgW = srcbitmap.Width;
            Bitmap bitmap = new Bitmap(1024, 768);
            BitmapData bitmapdata = bitmap.LockBits(new Rectangle(new Point(0, 0), bitmap.Size),
                ImageLockMode.ReadWrite,
               PixelFormat.Format24bppRgb);
            unsafe
            {
                byte* sourcebyte = (byte*)(bitmapdata.Scan0.ToPointer());
                int h0 = (multiple - 1) * pt.Y + deltaPt.Y;
                int w0 = (multiple - 1) * pt.X + deltaPt.X;
                if (h0 <= 0 || w0 <= 0) { h0 = 0; w0 = 0; }
                for (int y = h0; y < h0 + 768; y++)//只取pt.y处768
                {
                    for (int x = w0; x < w0 + 1024; x++)//只取pt.x处1024
                    {
                        long index = (x / multiple) + (y / multiple) * orgW;//行扫描宽度
                        tempImage3[(y - h0) * _RoiW + (x - w0)] = sourcebyte[0] = glob_buffer8[index];
                        sourcebyte[1] = glob_buffer8[index];
                        sourcebyte[2] = glob_buffer8[index];
                        sourcebyte += 3;
                    }
                }
            }
            bitmap.UnlockBits(bitmapdata);
            return bitmap;
        }

其实,第一次实现后,坐在那里,感到自己像图像中那个点一样,随着放大和缩小,自己在时光中穿越,你会发现时光倒流是非常难的,但有一种可能,就是永远在一个点放大缩小(你不仅可以到达未来,还可以回到过去,从前面的推演也可以论证,但是只要你移动了,想要回原来的点,可能性微乎其微!)。

待续(慢慢来!...........)每天一点小改变☺

我的邮箱liuganggang_1978@163.com;734523623@qq.com

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值