图像处理:指针变为nullptr而不重置它

时间:2019-06-07 12:04:37

标签: c++ c++-cli clr managed-c++

我正在一个项目中,该项目逐行恢复图像,并且必须重新着色图像内部的所有对象。我们的图像是实时收集的,并且每次调用我们都会收到一个1D byte[]数组。将每个1D阵列彼此重叠放置即可重建2D图像。该程序具有300个数组的缓冲区,该缓冲区足够显示每个对象。

数组中的数据是与颜色对应的数值。对象通常具有几种颜色,并且此代码必须使用最新的颜色为每个对象重新着色。

最初,该代码是用C#编写的,但是我遇到了一些性能问题,因此该程序适用于具有C ++的CLI / CLR项目,可以访问指针,从而极大地提高了速度。

对于数组中的每个像素,我实例化一个 Product 类,其中包含有关当前像素的数据。每个 Product 类都包含一个指向 Info 类的指针,该类包含有关当前对象的数据。该程序查看先前的相邻像素,并确定该像素是否属于同一对象。如果是这样,当前像素的 Product 类中的 Info 指针将指向前一个像素的 Info 类。这样,当计算整个对象的每种颜色时,我只需要更新 Info 类中最新出现的颜色索引即可更新每个像素的颜色,从而为整个对象重新着色。 / p>

这是循环的主要代码:

    void ProductsClipping::ProcessClippingFrame(array<unsigned char>^% CurrentProcessingFrame) {
        Monitor::Enter(obj);
        try {
            // Update Current Buffer Index
            BufferIndex++;
            if (BufferIndex >= BufferSize) BufferIndex = 0;

            // Get Current Frame
            CurrentProductFrame = ProductResult[BufferIndex];

            // Update Result Buffer Index
            ResultBufferIndex++;
            if (ResultBufferIndex >= BufferSize) ResultBufferIndex = 0;

            // Get Result Frame
            ResultFrame = ProductResult[ResultBufferIndex];

            // Process each pixel
            for (int i = 0; i < PixelsCount; i++) {
                Product^ LastProduct = LastProductFrame[i];

                if (LastProduct != nullptr && LastProduct->ProductInfo != nullptr && LastProduct->ProductInfo->BufferIndex != BufferIndex) {
                    LastProduct->ProductInfo->Height++;
                    LastProduct->ProductInfo->BufferIndex = BufferIndex;
                    LastProduct->ProductInfo->isResetMax = true;
                    LastProduct->ProductInfo->isActive = false;
                    LastProduct->UpdateProductIndex();
                }

                // If product in this pixel 
                if (CurrentProcessingFrame[i] > 0) {
                    bool hasParent = false;

                    // If last pixel don't belong to this product
                    if (CurrentProductFrame[i] == nullptr) CurrentProductFrame[i] = gcnew Product;
                    Product^ CurrentProduct = CurrentProductFrame[i];

                    // Check if has a particle in above pixel
                    if (LastProduct != nullptr && LastProduct->ProductID > 0) {
                        CurrentProduct->Update_Info(LastProduct->ProductInfo, LastProduct->ProductID, false);
                        hasParent = true;
                    }
                    Product^ PreviousProduct = i > 0 ? CurrentProductFrame[i - 1] : nullptr;

                    // Check if is a particle in the left of the pixel
                    if (PreviousProduct != nullptr && PreviousProduct->ProductID > 0) {
                        // If has particle above and in the left of pixel and the two particle is not the same
                        if (hasParent) {
                            if (PreviousProduct->ProductID != CurrentProduct->ProductID) {
                                PreviousProduct->Update_Info(CurrentProduct->ProductInfo, CurrentProduct->ProductID, true);
                            }
                        } else {
                            CurrentProduct->Update_Info(PreviousProduct->ProductInfo, PreviousProduct->ProductID, false);
                            hasParent = true;
                        }
                    }

                    if (!hasParent) {
                        if (i + 1 < CurrentProcessingFrame->Length && CurrentProcessingFrame[i + 1] > 0) {
                            CurrentProductFrame[i + 1] = CurrentProduct;

                            // End of product
                            if (LastProduct != nullptr && LastProduct->IsEndOfProduct && i == LastProduct->ProductInfo->LastMax) {
                                LastProduct->Close();
                            }
                            continue;
                        } else {
                            CurrentProduct->ProductID = ProductID;
                            ProductID++;
                        }
                    }

                    // If first pixel of product. Initialize information data
                    if (CurrentProduct->ProductInfo == nullptr) {
                        CurrentProduct->Initialize_Info(gcnew Info());
                        CurrentProduct->ProductInfo->ID = CurrentProduct->ProductID;
                        CurrentProduct->ProductInfo->BufferIndex = BufferIndex;
                    }
                    CurrentProduct->ProductInfo->LastMax = (CurrentProduct->ProductInfo->isResetMax) ? i : Math::Max(i, CurrentProduct->ProductInfo->LastMax);
                }

                // If End of product
                if (LastProduct != nullptr && LastProduct->IsEndOfProduct && i == LastProduct->ProductInfo->LastMax) LastProduct->Close();
                ResultFrame[i] = nullptr;
            }
            LastProductFrame = CurrentProductFrame;
        } finally { Monitor::Exit(obj); }
    }

这是带有 Info 指针的 Product 类的代码。

ref class Product {
    private:
        Info^ *_ProductInfo = nullptr;

    public:
        unsigned int ProductID;
        property Info^ ProductInfo {
            Info^ get() {
                if (!_ProductInfo) return nullptr;
                return *_ProductInfo;
            }
        }

        property bool IsEndOfProduct {
            bool get() { return ProductInfo != nullptr && ProductInfo->isOpen && !ProductInfo->isActive; }
        }

        void Update_Info(Info^ NewInfo, unsigned int NewProductID, bool isBelongOtherProduct) {
            if (NewInfo != nullptr) NewInfo->isActive = true;
            ProductID = NewProductID;
            _ProductInfo = &NewInfo;
        }

        void Initialize_Info(Info^ NewInfo) {
            _ProductInfo = &NewInfo;
        }

        void Close() {
            ProductInfo->isOpen = false;
        }
};

我遇到的问题是,对于对象中的第一个像素,指针正确指向 Info 类,但是在下一次迭代中,如果要将下一个像素设置为相同的< em> Info 类,第一个指针变为nullptr

编辑::添加了调用循环的测试代码:

public partial class Form1 : Form
{
    byte[][] Frame = new byte[][]
    {
                new byte[]{ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 },
                new byte[]{ 0, 1, 1, 0, 0, 1, 1, 0, 0, 0 },
                new byte[]{ 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
                new byte[]{ 0, 0, 1, 1, 1, 1, 0, 1, 0, 0 },
                new byte[]{ 0, 0, 0, 1, 0, 1, 0, 1, 0, 0 },
                new byte[]{ 0, 0, 1, 0, 0, 1, 1, 1, 0, 0 },
                new byte[]{ 0, 0, 1, 1, 1, 1, 1, 0, 0, 0 },
                new byte[]{ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 },
                new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    };

    ProductsClipping ClippingFrame;

    public Form1()
    {
        InitializeComponent();

        int NbArrays = Frame.Length;

        for (int i = 0; i < NbArrays; i++)
        {
            ClippingFrame.ProcessClippingFrame(ref Frame[i]);
        }
    }
}

0 个答案:

没有答案