我正在一个项目中,该项目逐行恢复图像,并且必须重新着色图像内部的所有对象。我们的图像是实时收集的,并且每次调用我们都会收到一个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]);
}
}
}