8000 Simulated fan-beam limited-angle reconstruction · Issue #40 · LLNL/LEAP · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Simulated fan-beam limited-angle reconstruction #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
stefenmax opened this issue May 22, 2024 · 30 comments
Closed

Simulated fan-beam limited-angle reconstruction #40

stefenmax opened this issue May 22, 2024 · 30 comments

Comments

@stefenmax
Copy link

Hi, I want to use LEAP to simulate the fan-beam limited-angle reconstruction, the following is my geomerty.

leapct.set_fanbeam(180, numRows, numCols, pixelSize, pixelSize, 0.5*(numRows-1), 0.5*(numCols-1), leapct.setAngleArray(numAngles, 90.0), sod, sdd)

The complete scanning process encompasses 720 views that are evenly distributed across 360 degrees. I want simulate the projection data with 180 views over a 90-degree span. But it will rasie the error

setParkerWeights: Not enough data!

Previouslt in astra toolbox it is easy to simulate like

limited_projGeom180 = astra.create_proj_geom('fanflat', 2.0, 768, np.linspace(0, np.pi/2, 180, endpoint=False), 512, 512)

Is there any similar way to do in LEAP? Thanks!

@kylechampley
Copy link
Collaborator

That is a warning (not an error message) coming from the FBP reconstruction. The forward projection does not care how many angles or their angular range. The command in your post works just fine. I see that you specified an angular range of 90 degrees and you did that correctly.

@stefenmax
Copy link
Author

The reconstructed image doesn't appear reasonable. The first image is the sinogram with 720 views, and the second is the sinogram with 180 views over a 90-degree span. Typically, the 180-view sinogram should be a quarter of the 720-view sinogram, but this isn't the case here. Additionally, the reconstructed image from the 180-view sinogram is not good can be seen in third image, while the 720-view sinogram produces a good reconstructed image. Below is my entire code.
720view sino
180view sino
180 view reconstruction image

leapct = tomographicModels()
numCols = 768
numRows = 1
sod = 512
sdd = 1024
pixelSize = 1
leapct.set_fanbeam(720, numRows, numCols, pixelSize, pixelSize, 0.5*(numRows-1), 0.5*(numCols-1), leapct.setAngleArray(numAngles, 360.0), sod, sdd) #full view
# leapct.set_fanbeam(180, numRows, numCols, pixelSize, pixelSize, 0.5*(numRows-1), 0.5*(numCols-1), leapct.setAngleArray(numAngles, 90.0), sod, sdd) #90 limited-angle view
leapct.set_volume(256, 256, 1,voxelWidth = pixelSize, voxelHeight=pixelSize) 
leapct.print_parameters()
g = leapct.allocateProjections() # shape is numAngles, numRows, numCols
f = leapct.allocateVolume() # shape is numZ, numY, numX
CT_img = np.load('./test_data/test_data.npy')
f = (CT_img - np.min(CT_img)) / (np.max(CT_img) - np.min(CT_img))
f = np.ascontiguousarray(f, dtype=np.float32)
leapct.project(g,f)
leapct.display(g)
leapct.FBP(g,f)
leapct.display(f)

@kylechampley
Copy link
Collaborator

Ya, I think you have a typo above. I did not see where you defined numAngles, but I assumed it was 720. So if this was the case, then the second set_fanbeam would have 180 angles, but your angle array has 720 angles over 90 degrees. Since you said you only had 180 angles, it would only use the first quarter of these angles which would be an angular range of 22.5 degrees. When I did this I got the same result as you.

Anyway, this typo should have been caught by my code and an error thrown. I'll add this error handling to the next release.

@stefenmax
Copy link
Author

Aha, sorry I made a stupid error.
This time I can got a resonable result. But there is a line in the middle. I tried the Forbild phantom same issue.
image

@kylechampley
Copy link
Collaborator

Ya, that is weird. I looked into the code and found out why LEAP was doing this. Apparently even though I printed that warning about the Parker Weights, they were still being applied to the data. Unfortunately, Parker Weights are not defined in this case and it was putting in a discontinuity.

Anyway, I fixed this issue. The bug fix is in the champley_dev branch. You can checkout this branch and give it a try now or you can wait a few days when I release a new version of LEAP.

To ensure you grabbed the right branch, you can run this command: leapct.about(). It should say version 1.12.

@stefenmax
Copy link
Author

For the version 1.12, where can I download the compliled file .dll, I still cannot manually complie LEAP by myself in windows. That is sad

@kylechampley
Copy link
Collaborator

Yes, it is sad. I'll upload .dll and .so files for the next release which will likely be sometime over the weekend.

The most common reasons one has trouble compiling LEAP is that they have the wrong version of cmake and Visual Studio. You need cmake version 3.23 or newer and Visual Studio 2019. Note that Visual Studio 2022 will NOT work.

You can also view the error messages if you try to install LEAP like this:
pip install . -v

@stefenmax
Copy link
Author

Sure, waiting for your next release!

@stefenmax
Copy link
Author

Hello again. I found another issue that I cannot solve. When I reconstruct an image using limited-angle scan and the object does not fill the entire image, there is a circle around it which I don't want. While the image like Forbild phantom will not have this issue even in the same geometry. The following is my geometry, I assume the full scan is 360 degree with 720 projections.

self.numRows = 1
self.numCols = 835
self.sod = 540
self.sdd = 950
self.pixelSize = 1
if ang_num == 120:
     leapct.set_fanbeam(240, self.numRows, self.numCols, self.pixelSize, self.pixelSize, 
     0.5*(self.numRows-1), 0.5*(self.numCols-1), leapct.setAngleArray(240, 120.0), self.sod, self.sdd)

image

@stefenmax stefenmax reopened this Jun 6, 2024
@kylechampley
Copy link
Collaborator

Yes, you need this function:
leapct.set_diameterFOV(d)
where d is the diameter of that circle, measured in mm. You can just give a huge number here if you don’t want any image masking.

@stefenmax
Copy link
Author

Thanks, it works!

@stefenmax
Copy link
Author

Hi, recently I found the set_diameterFOV is not w 8000 orked to my another data.
If I don't set the FOV, the result is kind of normal like the left, but when I set the FOV a big number like 9999, the result is weired.
Could you help me find what happened?
image

@stefenmax stefenmax reopened this Jun 17, 2024
@kylechampley
Copy link
Collaborator

If you change the display window, can you see the reconstruction? If you send me your data and script, I can look deeper into this.

@hws203
Copy link
hws203 commented Jun 18, 2024

I guess that this issue is similar to my micro-coil case, when there is no mask with big FOV number, the 4 corner sides have very bright pixels value, so after normalize this image with this bright criteria, then inner side image looks almost dark one but actually it has. Please crop the inner area and re-normalize the image again, then I hope you can find it .

@stefenmax
Copy link
Author

@hws203 yes, indeed the 4 corner sides hace very bright pixels. But I want the full size of limited-angle image not the cropped one. Hope kyle can help me solve that. Thanks for your help.
@kylechampley yes, after adjust the display window I can see the reconstruction but not the one I want. It looks weired. Already sent the script and data. Thanks
image

@kylechampley
Copy link
Collaborator

@stefenmax it looks like your projections are truncated. You generated your projections with an image that has values the extend past the field of view. The reason you see that really bright outline is from the ramp filter being applied to zero-padded data. Anyway, all you have to do is use the following command anywhere before you run the FBP reconstruction.
leapct.set_truncatedScan(True)

@kylechampley
Copy link
Collaborator

BTW, here is the result once I add that line to your script:
image

@stefenmax
Copy link
Author

Thank you.
But if I didn't set the truncatedScan.
Does that mean I need to adjust the detector parameter to avoid extending the field of view?

@kylechampley
Copy link
Collaborator

That's up to you. Yes, you could make the voxel size smaller to shrink the object until the projections are not truncated. I guess my recommendation is to get the parameters to the real values from the scanner.

@stefenmax
Copy link
Author

Hello again, I believe this time it's bug in the 3D reconstruction using ASD-POCS. The FBP worked in my dataset(10 npy images). But when I want to use ASD-POCS to process the limited-angle image. Some slices will showed like below. I sent the script and data to you, thanks for your time!
image

@kylechampley
Copy link
Collaborator

I found and fixed the issue. It was with the sensitivity calculation (P*1). I happen to be releasing a new version of LEAP tomorrow, so this bug fix will be included.

I did want to make a few comments though. First of all, your class is called FanBeam, but you are using cone-beam. Was this intentional?

Second of all, your reconstruction slices extend beyond the top and bottom of the detector. This contibuted to the bug you saw. You are using the same voxelHeight as pixelHeight, but note that the cone-beam geometry is a diverging geometry so the beam height at the origin is only sod/sdd * numRows * pixelHeight = 5.6842 mm, but your reconstruction volume is 10 mm tall. That means a large portion of your reconstruction is not seen by your detectors. Usually people scale their voxel sizes by sod/sdd, i.e.,
voxelWidth = sod/sdd * pixelWidth
voxelHeight = sod/sdd * pixelHeight
I recommend you do this or you use fewer reconstruction slices.

Make sense? Let me know if you need further clarification.

@stefenmax
Copy link
Author

Thank you for your prompt response and professional feedback.

For your first question, initially, I used one image to test and set the geometry to fan-beam for simplicity. Later, I intended to extend it to 3D, but the name remained unchanged.

Regarding your second comment, I acknowledge there are issues with the parameter settings. After scaling my voxel size as you suggested, the ASD_POCS result improved slightly, but the FDK result remained nearly the same. I have a question about why does the FDK result still produce reasonable outcomes even a significant portion of reconstruction is not detected by my detectors.?

@kylechampley
Copy link
Collaborator

Sure, no problem.

If your model is a good match to the measured data, then iterative reconstruction will outperform FBP/FDK, but analytic reconstruction, e.g., FBP/FDK is generally more robust than iterative reconstruction when it comes to model mismatch.

The other reason FDK looks OK is due to the zeroth order extrapolation I use off the bottom and top of the detector as discussed in issue #56.

Anyway, I just posted a new version of LEAP, v1.15, which fixes your original issue. You should now get good results from ASDPOCS using this version.

@kylechampley
Copy link
Collaborator

@stefenmax I'm going to close this issue because I think it has been resolved, but feel free to reopen it or open a new issue if something else arises.

@stefenmax
Copy link
Author

Hi, recently I updated the code from 1.16 to 1.20 cause I want to speed the TV function. It works on directly use the LEAP to reconstruct. But when I integrate it to my neural network. The GPU memory is not enough. In 1.16 it only cost my 8GB. But now even I'm using 40GB A100. It raises the following error. Can you help me to figured out what's going on? Thanks!
image
image

@kylechampley
Copy link
Collaborator

Hmm, that's annoying. This must be some kind of memory leak. I have not noticed this issue myself, so I will need some help in reproducing the issue. Could you please send me the information that you get from running this command:

leapct.print_parameters()

Basically I want to know the size of your CT volume.

@kylechampley kylechampley reopened this Aug 30, 2024
@stefenmax
Copy link
Author

Sorry for the late response. Here is the parameter I use:
image

@kylechampley
Copy link
Collaborator

Oh, you've got a very small volume. OK, I'll look for a memory leak using data of this size and the ASDPOCS algorithm.

FYI, I just posted a new version which makes a small change to the TV functions. It may resolve your issue, but I can't be certain. It also should help further improve TV speed for small volumes.

@stefenmax
Copy link
Author

The new version of LEAP indeed works. Thanks for your keep updated!

@kylechampley
Copy link
Collaborator

Glad to hear it! Another way to improve speed is to run the following command.

leapct.set_numTVneighbors(6)

It might give you results that aren’t quite as good but should improve speed by about a factor of 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
0