ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 How to update images in parallel
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

supersk

99 Posts

Posted - May 27 2024 :  04:37:19  Show Profile  Reply
When opening a large-sized TIFF image and performing certain processing on the image, it will be found that the image update process is relatively slow, but the CPU utilization rate is relatively low.So how to update images in parallel?

xequte

38610 Posts

Posted - May 27 2024 :  17:02:16  Show Profile  Reply
Hi

Do you mean use parallel processing to perform simultaneous operations on one image, or on multiple images?

Nigel
Xequte Software
www.imageen.com
Go to Top of Page

supersk

99 Posts

Posted - May 27 2024 :  20:22:05  Show Profile  Reply
The first one.I want to parallel process in the BeginImageProcessing and EndImageProcessing.

 if not proc.BeginImageProcessing([ie24RGB], x1, y1, x2, y2, 'CustomNegative', ProcBitmap, mask) then
    exit;
  for y := y1 to y2-1 do begin
    px := ProcBitmap.Scanline[y];
    for x := x1 to x2-1 do
    begin
      with px^ do
      begin
        r := 255-r;
        g := 255-g;
        b := 255-b;
      end;
      inc(px);
    end;
  end;
  // finalize
  proc.EndImageProcessing(ProcBitmap, mask);
Go to Top of Page

supersk

99 Posts

Posted - May 27 2024 :  20:25:18  Show Profile  Reply
To put it another way, I can implement parallel image processing in the GPU, but the image update part is still very slow. Therefore, how to update the content of an image in parallel.
Go to Top of Page

xequte

38610 Posts

Posted - May 28 2024 :  00:41:29  Show Profile  Reply
Hi

Here is an example of using Parallel.For() to process an image in simultaneous batches:

http://www.imageen.com/files/Other/ThreadedProcessing2_Image.zip


I tested various batch sizes (Left value: Standard processing, Right value: Parallel processing):

10: 638ms vs 194ms
50: 589ms vs 113ms
100 584ms vs 97ms
500: 590ms vs 115ms



Nigel
Xequte Software
www.imageen.com
Go to Top of Page

supersk

99 Posts

Posted - Jun 06 2024 :  02:53:23  Show Profile  Reply
The sample program is not what I want. I hope to be able to quickly load and process images, especially large-sized images. Using the sample program: display to load a large-sized dicom file (10k×5k) is three times slower than the software RadiAnt, so I want to use a parallel method to render the image. For updating complete images, you can use a parallel method to accelerate the process, which can achieve a speedup of about 3 times. However, for updating images in selected areas, I have adopted the following method:

void __fastcall TImageForm::UpdateImagePixels(WINSTRETCHPARAS &winStrechPara)
{
	TIEBitmap *ProcBitmap;
	TIEMask *mask;
	int x1, y1, x2, y2;
	if (!ImgEnMain->Proc->BeginImageProcessing(Hyiedefs::TIEPixelFormats()<<ie24RGB,
		x1, y1, x2, y2, "FloatStrech", ProcBitmap, mask))
		return;
int CPUCoreCount = ImageParas.CPUCoreCount;
    std::vector<std::thread> threads;
    const int chunkSize = (y2 - y1) / CPUCoreCount; // 
	TIERectangle  sel;
	sel = ImgEnMain->SelectedRect;
    for (int i = 0; i < CPUCoreCount; ++i) {
        int start = i * chunkSize;
        int end = (i == CPUCoreCount - 1) ?  (y2 - y1) : start + chunkSize;
        threads.push_back(std::thread(ppkSetBlockPixels, std::ref(ImgEnMain),  std::ref(RImage),
        	std::ref(mask), std::ref(sel), 	std::ref(winStrechPara), start, end, x1, x2));
    }
	ImgEnMain->Proc->EndImageProcessing(ProcBitmap, mask);
}
int __fastcall TImageForm::ppkSetBlockPixels(TImageEnView *imgen, TEImage *RImage,  TIEMask *mask,
							TIERectangle  &sel, WINSTRETCHPARAS &winStrechPara,
                            int startln, int endln, int startr, int endr)
{
    unsigned short xyGray;
    Hyiedefs::PRGB px;
    int x,y;
    Hyiedefs::TRGB tmppx;
    px = &tmppx;
	for (int i = startln; i < endln; i++) {
		y = sel.y + i;
		for (int j = startr; j <= endr; j++) {
			x = sel.x + j;
            xyGray = RImage->ProcData[y][x] * FIMGScale;
	
			if (winStrechPara.mbGrayStrech) {
				xyGray = winStrechPara.GrayHisto[xyGray];
			}
			if (winStrechPara.mbWindowedShow) {
				if (xyGray < winStrechPara.GWinLowvalue) {
					xyGray = 0;
				}
				if (xyGray > winStrechPara.GWinUpvalue) {
					xyGray = 255;
				}
			}
            if (imgen->Selected){
            	if(mask->GetPixel(x, y) > 0) {
                	setPixelColor(px, xyGray);
                    imgen->IEBitmap->Pixels_ie24RGB[x][y] = *px;
                }
			}else{
				setPixelColor(px, xyGray);
                imgen->IEBitmap->Pixels_ie24RGB[x][y] = *px;
            }
		}
	}
    return 1;
}

But this method doesn't work. Why?
Go to Top of Page

xequte

38610 Posts

Posted - Jun 06 2024 :  23:06:18  Show Profile  Reply
Hi

What specifically fails when you use your code?

Are you sure ImageEnView1.Update() is called *after* all the threads complete their work?

Try simplifying the code by removing the BeginImageProcessing/EndImageProcessing calls (which seem unnecessary here) and using the full image values for x1, y1, x2, y2.

Nigel
Xequte Software
www.imageen.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: